KJB
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sample_step.h
Go to the documentation of this file.
1 /* $Id: sample_step.h 17393 2014-08-23 20:19:14Z predoehl $ */
2 /* =========================================================================== *
3  |
4  | Copyright (c) 1994-2010 by Kobus Barnard (author)
5  |
6  | Personal and educational use of this code is granted, provided that this
7  | header is kept intact, and that the authorship is not misrepresented, that
8  | its use is acknowledged in publications, and relevant papers are cited.
9  |
10  | For other use contact the author (kobus AT cs DOT arizona DOT edu).
11  |
12  | Please note that the code in this file has not necessarily been adequately
13  | tested. Naturally, there is no guarantee of performance, support, or fitness
14  | for any particular task. Nonetheless, I am interested in hearing about
15  | problems that you encounter.
16  |
17  | Author: Kyle Simek, Ernesto Brau
18  * =========================================================================== */
19 
20 #ifndef SAMPLE_STEP_H_INCLUDED
21 #define SAMPLE_STEP_H_INCLUDED
22 
24 #include "sample_cpp/sample_base.h"
26 #include "prob_cpp/prob_sample.h"
27 #include "l_cpp/l_exception.h"
28 
29 /* ========================================================================= *
30  * ========================================================================= *
31  * == METROPOLIS HASTINGS == *
32  * ========================================================================= *
33  * ========================================================================= */
34 
49 template<typename Model, typename Proposer = typename Mh_model_proposer<Model>::Type >
51 {
52 public:
54 // typedef typename Mh_model_proposer<Model>::Type Proposer;
55 
57 
58  //virtual const char* get_type() const{return "Abstract_mh_step";}
76  Step_log<Model> run_step(Model& m, double lt_m, double& accept_prob, boost::optional<Model&> proposed_state_out = boost::none) const;
77 
88  virtual Step_log<Model> operator()(Model& m, double lt_m) const;
89 
90  virtual double get_temperature() const { return 1.0; }
91 
92  virtual ~Abstract_mh_step(){}
93 
95  virtual Mh_proposal_result propose(const Model& m, Model& m_p) const = 0;
96 
98  virtual double l_target(const Model& m) const = 0;
99 
100  // optional callback when model is accepted
101  virtual void on_accept() const {}
102  // optional callback when model is rejected
103  virtual void on_reject() const {}
104 
105 protected:
111  virtual bool record_extra() const { return false; }
112 
113 protected:
114  mutable boost::optional<Model> tmp_model_;
115 };
116 
117 /* \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */
118 
119 template<typename Model, typename Proposer>
120 Step_log<Model> Abstract_mh_step<Model, Proposer>::run_step(Model& m, double lt_m, double& accept_prob, boost::optional<Model&> proposed_state_out) const
121 {
122  // Just refactored this so
123  // (a) no default construction is necessary
124  // (b) the proposed object is only allocated once per the lifetime
125  // of the object, instead of once per iteration as previously
126  // Kyle, December 11, 2011
127  if(!tmp_model_)
128  {
129  // copy constructor is called
130  tmp_model_ = m;
131  }
132 
133  Model& m_p = *tmp_model_;
134  double lt_m_p;
135  double lt_final;
136 
137  // propose model and compute probabilities/densities
138  Mh_proposal_result p_res = propose(m, m_p);
139 
140  // if the caller has requested a copy of the proposed state, copy it here
141  if(proposed_state_out)
142  *proposed_state_out = m_p;
143 
144  double q_m_p = p_res.fwd_prob;
145  double q_m = p_res.rev_prob;
146 
147  if(p_res.no_change)
148  {
149  lt_m_p = lt_m;
150  }
151  else
152  {
153  // get log-target distribution of the proposed model
154  lt_m_p = l_target(m_p);
155  }
156 
157  // compute acceptance probability
158  accept_prob = (lt_m_p - lt_m + q_m - q_m_p) / get_temperature();
159 
160  double u = std::log(kjb::sample(kjb::Uniform_distribution(0, 1)));
161 
162  bool accepted;
163 
164  if(u < accept_prob)
165  {
166  // Model type should specialize swap to get best performance
167  using std::swap;
168  swap(m, m_p);
169  lt_final = lt_m_p;
170  accepted = true;
171  on_accept();
172  }
173  else
174  {
175  lt_final = lt_m;
176  accepted = false;
177  on_reject();
178  }
179 
180  Step_result<Model> result("mh-", p_res.type, accepted, lt_final, accepted ? &m : &m_p);
181  // TODO: uncomment after NIPS
182 // Step_result<Model> result("mh", p_res.type, accepted, lt_final, accepted ? &m : &m_p);
183 
184  if(record_extra())
185  {
186  result.extra["mh_p_fwd"] = lt_m_p;
187  result.extra["mh_p_rev"] = lt_m;
188  result.extra["mh_q_fwd"] = q_m_p;
189  result.extra["mh_q_rev"] = q_m;
190  result.extra["mh_accept"] = accept_prob;
191  result.extra["no_change"]= p_res.no_change;
192  }
193 
194  return Step_log<Model>(result);
195 }
196 
197 template<typename Model, typename Proposer>
199 {
200  double accept_prob;
201  return run_step(m, lt_m, accept_prob);
202 }
203 
204 /* \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */
205 
218 template<typename Model, typename Proposer_type = typename Mh_model_proposer<Model>::Type >
219 class Basic_mh_step : public Abstract_mh_step<Model, Proposer_type>
220 {
221 public:
223 
225  typedef Proposer_type Proposer;
226 
237  Basic_mh_step(const Target_distribution& log_target, const Proposer_type& proposer) :
238  Parent(),
239  m_log_target(log_target),
240  m_proposer(proposer),
241  m_temperature(1.0),
242  m_record_extra(false)
243  {}
244 
245 // /**
246 // * @brief Initializes target and proposer functors (or functions)
247 // * to the given arguments.
248 // *
249 // * @param log_target Target_distribution object used to initialize
250 // * internal target distribution used in operator().
251 // *
252 // * @param proposer Proposer_type object used to initialize internal
253 // * proposer used in operator().
254 // *
255 // * @param default_model If Model is not default-constructible, you need
256 // * to provide a model to initialize new models.
257 // **/
258 // Basic_mh_step(const Target_distribution& log_target, const Proposer_type& proposer, const Model& default_model) :
259 // Parent(),
260 // m_log_target(log_target),
261 // m_proposer(proposer),
262 // m_temperature(1.0),
263 // m_record_extra(false)
264 // {}
265 //
266 // /**
267 // * @brief Copy-constructor
268 // */
269 // Basic_mh_step(const Basic_mh_step<Model, Proposer_type>& step) :
270 // Parent(step),
271 // m_log_target(step.m_log_target),
272 // m_proposer(step.m_proposer),
273 // m_temperature(1.0),
274 // m_record_extra(false)
275 // {}
276 
277  virtual ~Basic_mh_step(){}
278 
279 // /**
280 // * @brief Assignment
281 // */
282 // Basic_mh_step& operator=(const Basic_mh_step<Model, Proposer_type>& step)
283 // {
284 // if(&step != this)
285 // {
286 // m_log_target = step.m_log_target;
287 // m_proposer = step.m_proposer;
288 // m_temperature = step.m_temperature;
289 // }
290 //
291 // return *this;
292 // }
293 
295  virtual Mh_proposal_result propose(const Model& m, Model& m_p) const
296  {
297  return m_proposer(m, m_p);
298  }
299 
301  virtual double l_target(const Model& m) const
302  {
303  return m_log_target(m);
304  }
305 
314  void set_target(const Target_distribution& target)
315  {
316  m_log_target = target;
317  }
318 
324  void record_extra(bool enable)
325  {
326  m_record_extra = enable;
327  }
328 
333  void set_temperature(double T)
334  {
335  m_temperature = T;
336  }
337 
338  virtual double get_temperature() const
339  {
340  return m_temperature;
341  }
342 
343 protected:
344  virtual bool record_extra() const
345  {
346  return m_record_extra;
347  }
348 
349  Proposer_type& get_proposer_()
350  {
351  return m_proposer;
352  }
353 
355  Proposer_type m_proposer;
357 
359 };
360 
361 
362 /* ========================================================================= *
363  * ========================================================================= *
364  * == GIBBS == *
365  * ========================================================================= *
366  * ========================================================================= */
367 
379 template<typename Model>
381 {
382 public:
386 
388 
393  virtual const Target_distribution& get_log_target() const = 0;
394 
399  virtual const Proposer& get_proposer() const = 0;
400 
405  virtual const Get_dimension& get_dimension_function() const = 0;
406 
407  //virtual const char* get_type() const{return "Abstract_gibbs_step";}
408 
415  virtual Step_log<Model> operator()(Model& m, double lt_m) const;
416 
418 };
419 
420 
421 /* \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */
422 
423 template<class Model>
425 {
426  const Target_distribution& l_target = get_log_target();
427  const Proposer& propose = get_proposer();
428  const Get_dimension& get_dimension = get_dimension_function();
429 
430  int num_vars = get_dimension(m);
431 
432  boost::optional<double> result;
433  for(int i = 0; i < num_vars; i++)
434  {
435  result = propose(m, i);
436  }
437 
438  if(!result)
439  {
440  result = l_target(m);
441  }
442  return Step_log<Model>(Step_result<Model>("gibbs", "gibbs", true, *result, &m));
443 }
444 
445 /* \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */
446 
459 template<typename Model>
461 {
462 public:
464 
466  typedef typename Parent::Proposer Proposer;
468 
480  (
481  const Target_distribution& log_target,
482  const Proposer& proposer,
483  const Get_dimension& get_dimension
484  ) :
485  Parent(),
486  m_log_target(log_target),
487  m_proposer(proposer),
488  m_get_dimension(get_dimension)
489  {}
490 
491 // /**
492 // * @brief Copy-constructor
493 // */
494 // Basic_gibbs_step(const Basic_gibbs_step<Model>& step) :
495 // Parent(step),
496 // m_log_target(step.m_log_target),
497 // m_proposer(step.m_proposer),
498 // m_get_dimension(step.m_get_dimension)
499 // {}
500 
501 // /**
502 // * @brief Assignment
503 // */
504 // Basic_gibbs_step& operator=(const Basic_gibbs_step<Model>& step)
505 // {
506 // if(&step != this)
507 // {
508 // m_log_target = step.m_log_target;
509 // m_proposer = step.m_proposer;
510 // }
511 //
512 // return *this;
513 // }
514 //
515  virtual const Target_distribution& get_log_target() const{ return m_log_target; }
516 
517  virtual const Proposer& get_proposer() const{ return m_proposer; }
518 
519  virtual const Get_dimension& get_dimension_function() const{ return m_get_dimension; }
520 
521  virtual ~Basic_gibbs_step(){}
522 
523 protected:
527 };
528 
529 
530 /* ========================================================================= *
531  * ========================================================================= *
532  * == HMC == *
533  * ========================================================================= *
534  * ========================================================================= */
535 
568 template<typename Model,
569  bool CONSTRAINED_TARGET = false,
570  bool INCLUDE_ACCEPT_STEP = true,
571  bool REVERSIBLE = true>
573 {
574 public:
580 
581  // constraint handling stuff
585 
587 
589  int num_dynamics_steps,
590  double alpha) :
591  m_num_dynamics_steps(num_dynamics_steps),
592  m_alpha(alpha),
593  m_first_p_full(is_first_p_full(alpha, INCLUDE_ACCEPT_STEP, REVERSIBLE)),
594  m_last_p_ignore(is_last_p_ignored(alpha, INCLUDE_ACCEPT_STEP, REVERSIBLE)),
595  m_temperature(1.0)
596  {}
597 
598  bool is_first_p_full(const bool alpha, const bool accept_step, const bool reversible)
599  {
600  // We'd like to avoid the final momentum update, if possible. It
601  // isn't avoidable if we have an accept step. If we discard
602  // the accept step, we have two options:
603  // There are two ways to skip the final momentum update:
604  // (a) If the momentum is completely replaced in every step
605  // (i.e. alpha == 0), the final momentum doesn't matter, so
606  // we can discard it without sacrificing anything.
607  // (b) If we perform partial replacement of momenta (alpha > 0),
608  // we can't discard the momentum update, so we'll roll it into
609  // the first momentum update, sacrificing reversibility.
610  //
611  // If you use partial momentum updates, and reversibility must be
612  // maintined, no optimizations may be used.
613  //
614  // We can summarize this logic in a truth table, which we build below.
615  //
616  // Inputs are encoded as follows:
617  // A = 1: accept/reject step is enabled
618  // A = 0: accept/reject step is skipped
619  //
620  // R = 1: reversibility must be maintained
621  // R = 0: reversibilty may be sacrificed.
622  //
623  // P = 1: partial momenta updates are performed
624  // P = 0: momenta are fully replaced at each iteration
625  //
626  // Outputs:
627  // f = 0: first momenta update is a half-update
628  // f = 1: " " " " full-update
629  // l = 0: last momemnta update is a half-update
630  // l = 1: " " " " ignored
631  //
632  // In other words, f=0 and l=0 means "use standard mcmc". Any
633  // other combination of outputs implies an optimization is used.
634  //
635  // A R P || f l comments
636  // -------------------------------
637  // 1 x x || 0 0 true HMC
638  // 0 0 0 || 0 1 still reversible
639  // 0 1 0 || 0 1
640  // 0 0 1 || 1 1 not reversible
641  // 0 1 1 || 0 0
642  //
643  // This results in the following boolean expressions:
644  //
645  // f = !A ^ !(R ^ P)
646  // l = !A ^ !R ^ P
647  //
648  // Here, 'v' means "or", '^' means "and".
649 
650 
651 
652  // Which of these methods to use
653  //
654  const bool partial_updates = (alpha > 0.0);
655  return !accept_step && !reversible && partial_updates;
656  }
657 
658  bool is_last_p_ignored(const bool alpha, const bool accept_step, const bool reversible)
659  {
660  const bool partial_updates = (alpha > 0.0);
661  // there's a truth table under is_first_p_full that explains this
662  // boolean logic.
663  return !accept_step && !(reversible && partial_updates);
664  }
665 
666 
669  m_alpha(ahs.m_alpha),
670  p(ahs.p),
674  {}
675 
676 // Abstract_hmc_step& operator=(const Abstract_hmc_step& ahs)
677 // {
678 // m_num_dynamics_steps = ahs.m_num_dynamics_steps;
679 // m_alpha = ahs.m_alpha;
680 // p = ahs.p;
681 // m_first_p_full = ahs.m_first_p_full;
682 // m_last_p_ignore = ahs.m_last_p_ignore;
683 // m_temperature = ahs.m_temperature;
684 // }
685 
697  virtual Step_log<Model> operator()(Model& q, double lt_q) const;
698 
703  virtual const Target_distribution& get_log_target() const = 0;
704 
709  virtual const Gradient& get_gradient() const = 0;
710 
715  virtual const Move_parameter& get_move_parameter() const = 0;
716 
721  virtual const Get_step_size& get_step_size_function() const = 0;
722 
727  virtual const Get_dimension& get_dimension_function() const = 0;
728 
729  void set_temperature(const double T) { m_temperature = T; }
730 
732  virtual bool record_extra() const = 0;
734 
739  virtual const Get_parameter& get_parameter_function() const = 0;
740 
745  virtual const Get_upper_bounds& get_upper_bounds_function() const = 0;
746 
751  virtual const Get_lower_bounds& get_lower_bounds_function() const = 0;
752 
754 
756 
762  virtual void post_move_callback(Model& /* q */, kjb::Vector& /* p */) const
763  {
764  return; // no-op
765  }
766 
767 
768  virtual ~Abstract_hmc_step(){}
769 
770 protected:
778 
783  double m_alpha;
784 
788  mutable kjb::Vector p;
789 
795 
797 };
798 
799 
800 /* \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */
801 
802 template<class Model, bool CONSTRAINED_TARGET, bool INCLUDE_ACCEPT_STEP, bool REVERSIBLE>
804 {
805  // ///////////////////////////////////////////////////////////////
806  // This variant of HMC is outlined in Horowitz (1991):
807  // "A generalized guided monte carlo algorithm."
808  // It allows us to choose between partial or complete stochastic
809  // replacement of momenta, without changing the algorithm. Neal's
810  // version exhibits random walk when using "partial updates," so
811  // we opted against it.
812  // ////////////////////////////////////////////////////////////////
813 
814  // get all components (functors, callbacks, tunable params, etc)
815  const Target_distribution& l_target = get_log_target();
816  const Gradient& compute_gradient = get_gradient();
817  const Move_parameter& move_parameter = get_move_parameter();
818  const Get_step_size& get_step_size = get_step_size_function();
819  const Get_dimension& get_dimension = get_dimension_function();
820 
821  // These are needed for constraint handling
822  const Get_parameter& get_parameter = get_parameter_function();
823  const Get_lower_bounds& get_lower_bounds = get_lower_bounds_function();
824  const Get_upper_bounds& get_upper_bounds = get_upper_bounds_function();
825 
826  size_t hmc_dim = get_dimension(q);
827 
828  // make sure dimension of p is the same as of the model
829  if(p.get_length() != static_cast<int>(hmc_dim))
830  {
831  p.zero_out(hmc_dim);
832  }
833 
834  // Sample new momentum -- using a partial update.
835  // Note: when m_alpha = 0 this algorithm becomes regular HMC
836  p *= m_alpha;
837  p += sqrt(1 - m_alpha * m_alpha) * kjb::sample(kjb::MV_gaussian_distribution(hmc_dim)) * sqrt(m_temperature);
838 
839  // Compute grad_U (which is -grad(log_target))
840  // and multiply times epsilon (grad_U never appears alone)
841  kjb::Vector epsilons = get_step_size(q);
842  kjb::Vector grad_x_eps = -1.0 * compute_gradient(q);
843  std::transform(grad_x_eps.begin(), grad_x_eps.end(), epsilons.begin(),
844  grad_x_eps.begin(), std::multiplies<double>());
845 
847  // leapfrog algorithm //
849 
850  Model q_star = q;
851 
852  kjb::Vector p_star = p;
853  if(m_first_p_full)
854  {
855  // OPTIMIZATION BRANCH
856  // We perform a full-step of the momentum.
857  //
858  // The normal algorithm calls for a 1/2 step here, but
859  // we offer an optimization that makes this a full step,
860  // and eliminates the final 1/2 step later on. This saves
861  // one gradient evaluation per iteration, which may be significant.
862  // Note: using this optimization, the algorithm is no longer true
863  // MCMC, because the step is not volume-preserving (and thus not reversible)
864  p_star -= grad_x_eps;
865  }
866  else
867  {
868  // We perform a half-step of the momentum
869  // (as per the normal leapfrog algorithm).
870  p_star -= grad_x_eps / 2.0;
871  }
872 
873  // needed for constraints
874  kjb::Vector lower_bounds;
875  kjb::Vector upper_bounds;
876 
877  // Alternate full steps for position and momentum
878  kjb::Vector etp(epsilons.size());
879  for(int i = 0; i < m_num_dynamics_steps; i++)
880  {
881  // Perform a full update of the parameters
882  // First compute epsilon x p_star
883  std::transform(epsilons.begin(), epsilons.end(), p_star.begin(),
884  etp.begin(), std::multiplies<double>());
885 
886  if(CONSTRAINED_TARGET)
887  {
888  // These are needed to handle constraints
889  lower_bounds = get_lower_bounds(q_star);
890  upper_bounds = get_upper_bounds(q_star);
891  }
892 
893  // should move_parameters do this loop in one step?
894  // Could be faster in some implementations...
895  // --Kyle, Feb 6 2011
896  for(size_t d = 0; d < hmc_dim; d++)
897  {
898  double mpb;
899  if(!CONSTRAINED_TARGET)
900  {
901  mpb = etp[d];
902  }
903  else
904  {
905  // HANDLING CONSTRAINTS
906  // We need to fix the position and momentum until they stop
907  // violating constraints. See Neal for details.
908  double q_d_p, q_d;
909  do
910  {
911  q_d = get_parameter(q_star, d);
912  q_d_p = q_d + etp[d];
913  if(q_d_p < lower_bounds[d])
914  {
915  q_d_p = (2 * lower_bounds[d] - q_d_p);
916  p_star[d] *= -1;
917  }
918 
919  if(q_d_p > upper_bounds[d])
920  {
921  q_d_p = (2 * upper_bounds[d] - q_d_p);
922  p_star[d] *= -1;
923  }
924  }while(q_d_p < lower_bounds[d] || q_d_p > upper_bounds[d]);
925  mpb = q_d_p - q_d;
926  }
927  move_parameter(q_star, d, mpb);
928  }
929 
930  // default: no-op
931  post_move_callback(q_star, p_star);
932 
933  // if (last_iteration && don't care about final value of p)
934  if(i == m_num_dynamics_steps - 1 && m_last_p_ignore)
935  {
936  /* do nothing */
937 
938  // OPTIMIZATION BRANCH
939  // Don't bother performing the final gradient evaluation, because either
940  // (a) the final momentum will be discarded, or
941  // (b) the final half-update of momentum was rolled into a full
942  // initial momentum update.
943  // In either case, this is no longer true MCMC, but could be "close enough,"
944  // and the benefits to running time may be worth it.
945  }
946  else
947  {
948  // update grad_U x epsilon.
949  grad_x_eps = -1.0 * compute_gradient(q_star);
950  epsilons = get_step_size(q_star);
951  std::transform(grad_x_eps.begin(), grad_x_eps.end(), epsilons.begin(),
952  grad_x_eps.begin(), std::multiplies<double>());
953 
954  }
955 
956  // Make a full step for the momentum, except at the end of the trajectory
957  if(i != m_num_dynamics_steps - 1)
958  {
959  p_star -= grad_x_eps;
960  }
961  }
962 
963  if(m_last_p_ignore)
964  {
965  /* Do nothing */
966  // OPTIMIZATION BRANCH (see above)
967  }
968  else
969  {
970  // Make a half step for momentum at the end.
971  p_star -= (grad_x_eps / 2.0);
972  }
973 
974  // Negate momentum at end of trajectory to make the proposal symmetric
975  p_star *= -1.0;
976 
978  // Accept or reject //
980 
981  double accept_prob;
982  double U_q_star = -l_target(q_star); // necessary even if accept_step = true, because sampler needs to know the log-target of the final model
983  double U_q = -lt_q;
984 
985  // TODO: may need to divide by step size here...
986  double K_p_star = p_star.magnitude_squared() / 2.0;
987  double K_p = p.magnitude_squared() / 2.0;
988 
989  if(INCLUDE_ACCEPT_STEP)
990  {
991 
992  // compute acceptance probability
993  accept_prob = (U_q - U_q_star + K_p - K_p_star) / m_temperature;
994  }
995  else
996  {
997  // at least 0 ensures acceptance
998  accept_prob = 0.00;
999  }
1000 
1001  double r = std::log(kjb::sample(kjb::Uniform_distribution(0, 1)));
1002  bool accepted;
1003  double lt_final;
1004 
1005  if(r < accept_prob)
1006  {
1007  // update the position and momentum
1008  // Note: specialize swap to get best performance
1009  using std::swap;
1010  swap(q, q_star);
1011  swap(p, p_star);
1012 
1013  // update log(target)
1014  lt_final = -U_q_star;
1015  accepted = true;
1016  }
1017  else
1018  {
1019  // Everything stays the same
1020  lt_final = lt_q;
1021  accepted = false;
1022  }
1023 
1024  // Negate momentum to avoid random walk.
1025  // true reversal of momentum only occurs when rejection occurs.
1026  // note: if alpha is not 0, this makes the step non-reversible
1027  p *= -1.0;
1028 
1029  Step_result<Model> result("hmc", accepted, lt_final);
1030 
1031  if(record_extra())
1032  {
1033  result.extra["hmc_u_rev"] = U_q;
1034  result.extra["hmc_u_fwd"] = U_q_star;
1035  result.extra["hmc_k_rev"] = K_p;
1036  result.extra["hmc_k_fwd"] = K_p_star;
1037  result.extra["hmc_accept"] = accept_prob;
1038  }
1039 
1040  return Step_log<Model>(result);
1041 }
1042 
1058 template<typename Model,
1059  bool CONSTRAINED_TARGET = false,
1060  bool INCLUDE_ACCEPT_STEP = true,
1061  bool REVERSIBLE = true>
1062 class Basic_hmc_step : public Abstract_hmc_step<Model, CONSTRAINED_TARGET, INCLUDE_ACCEPT_STEP, REVERSIBLE>
1063 {
1064 public:
1065  typedef Abstract_hmc_step<Model, CONSTRAINED_TARGET,
1066  INCLUDE_ACCEPT_STEP, REVERSIBLE> Parent;
1067 
1069  typedef typename Parent::Gradient Gradient;
1073 
1074  // constraint handling stuff
1078 
1106  (
1107  const Target_distribution& log_target,
1108  int num_dynamics_steps,
1109  const Gradient& gradient,
1110  const Move_parameter& move_parameter,
1111  const Get_step_size& get_step_size,
1112  const Get_dimension& get_dimension,
1113  double alpha = 0.0
1114  ) :
1115  Parent(num_dynamics_steps, alpha),
1116  m_log_target(log_target),
1117  m_gradient(gradient),
1118  m_move_parameter(move_parameter),
1119  m_get_step_size(get_step_size),
1120  m_get_dimension(get_dimension),
1121  m_record_extra(false),
1122  m_get_parameter(),
1125  {}
1126 
1128  (
1129  const Target_distribution& log_target,
1130  int num_dynamics_steps,
1131  const Gradient& gradient,
1132  const Move_parameter& move_parameter,
1133  const Get_step_size& get_step_size,
1134  const Get_dimension& get_dimension,
1135  const Get_parameter& get_parameter,
1136  const Get_lower_bounds& get_lower_bounds,
1137  const Get_upper_bounds& get_upper_bounds,
1138  double alpha = 0.0
1139  ) :
1140  Parent(num_dynamics_steps, alpha),
1141  m_log_target(log_target),
1142  m_gradient(gradient),
1143  m_move_parameter(move_parameter),
1144  m_get_step_size(get_step_size),
1145  m_get_dimension(get_dimension),
1146  m_record_extra(false),
1147  m_get_parameter(get_parameter),
1148  m_get_lower_bounds(get_lower_bounds),
1149  m_get_upper_bounds(get_upper_bounds)
1150  {}
1151 
1155  void record_extra(bool enable)
1156  {
1157  m_record_extra = enable;
1158  }
1159 
1160 // /**
1161 // * @brief Copy-constructor
1162 // */
1163 // Basic_hmc_step(const Basic_hmc_step<Model>& step) :
1164 // Parent(step),
1165 // m_log_target(step.m_log_target),
1166 // m_gradient(step.m_gradient),
1167 // m_move_parameter(step.m_move_parameter),
1168 // m_get_step_size(step.m_get_step_size),
1169 // m_get_dimension(step.m_get_dimension)
1170 // {}
1171 
1172 // /**
1173 // * @brief Assignment
1174 // */
1175 // Basic_hmc_step& operator=(const Basic_hmc_step<Model>& step)
1176 // {
1177 // if(&step != this)
1178 // {
1179 // Parent::operator=(step);
1180 // m_log_target = step.m_log_target;
1181 // m_gradient = step.m_gradient;
1182 // m_move_parameter = step.m_move_parameter;
1183 // m_get_step_size = step.m_get_step_size;
1184 // m_get_dimension = step.m_get_dimension;
1185 // }
1186 //
1187 // return *this;
1188 // }
1189 
1190  void set_post_move_callback(const boost::function2<void, Model&, kjb::Vector&>& f)
1191  {
1193  }
1194 
1195  virtual ~Basic_hmc_step(){}
1196 
1197  virtual const Target_distribution& get_log_target() const{ return m_log_target; }
1198 
1199  virtual const Gradient& get_gradient() const{ return m_gradient; }
1200 
1201  virtual const Move_parameter& get_move_parameter() const{ return m_move_parameter; }
1202 
1203  virtual const Get_step_size& get_step_size_function() const{ return m_get_step_size; }
1204 
1205  virtual const Get_dimension& get_dimension_function() const{ return m_get_dimension; }
1206 
1208  virtual bool record_extra() const
1209  {
1210  return m_record_extra;
1211  }
1212 
1213  // \/ \/ for constraint handling \/ \/
1214  virtual const Get_parameter& get_parameter_function() const{ return m_get_parameter; }
1215 
1217 
1219 
1220  virtual void post_move_callback(Model& q, kjb::Vector& p) const
1221  {
1223  return m_post_move_callback(q,p);
1224  }
1225 
1226 protected:
1232 
1234 
1235  // constraint handling
1239 
1240  boost::function2<void, Model&, kjb::Vector&> m_post_move_callback;
1241 };
1242 
1251 template<class Model, bool REVERSIBLE = true>
1253 {
1255 };
1256 
1257 
1258 #endif /*SAMPLE_STEP_H_INCLUDED */
1259 
const int m_num_dynamics_steps
The number of leapfrog steps in the trajectory, "choosing a suitable trajectory length is crucial if ...
Definition: sample_step.h:777
virtual const Get_dimension & get_dimension_function() const
Returns a reference to the mechanism for computing the dimension of the model.
Definition: sample_step.h:1205
virtual bool record_extra() const
Definition: sample_step.h:111
virtual const Target_distribution & get_log_target() const
Copy-constructor.
Definition: sample_step.h:515
Proposer_type & get_proposer_()
Definition: sample_step.h:349
virtual const Get_parameter & get_parameter_function() const
Returns a reference to the mechanism for getting the value of a dimension of the model.
Definition: sample_step.h:1214
virtual const Target_distribution & get_log_target() const
Returns a reference to the target distribution. Returned object must comply with the ModelEvaluator c...
Definition: sample_step.h:1197
Definition: sample_step.h:460
Parent::Get_lower_bounds Get_lower_bounds
Definition: sample_step.h:1076
Parent::Proposer Proposer
Definition: sample_step.h:466
virtual void on_reject() const
Definition: sample_step.h:103
boost::function2< void, Model &, kjb::Vector & > m_post_move_callback
Definition: sample_step.h:1240
virtual const Move_parameter & get_move_parameter() const =0
Returns a reference to the parameter-changing mechanism. Must comply with the ChangeParameter concept...
virtual bool record_extra() const =0
if true is returned, the step log will contain metadata about the step
bool is_last_p_ignored(const bool alpha, const bool accept_step, const bool reversible)
Definition: sample_step.h:658
Get_parameter m_get_parameter
Definition: sample_step.h:1236
double fwd_prob
log forward proposal probability
Definition: sample_base.h:379
virtual Mh_proposal_result propose(const Model &m, Model &m_p) const
Assignment.
Definition: sample_step.h:295
virtual Step_log< Model > operator()(Model &m, double lt_m) const
Runs a step of Gibbs on a model m.
Definition: sample_step.h:424
size_type size() const
Alias to get_length(). Required to comply with stl Container concept.
Definition: m_vector.h:510
void set_target(const Target_distribution &target)
Definition: sample_step.h:314
virtual void on_accept() const
Definition: sample_step.h:101
virtual const Get_upper_bounds & get_upper_bounds_function() const =0
Returns a reference to the mechanism for getting the upper bounds of a function.
Model_evaluator< Model >::Type Target_distribution
Definition: sample_step.h:383
BOOST_CONCEPT_ASSERT((BaseModel< Model >))
Proposer_type Proposer
Definition: sample_step.h:225
Indicates the result of an MH proposal. It is simply a pair of probabilities, forward and backward...
Definition: sample_base.h:334
Model_parameter_evaluator< Model >::Type Get_upper_bounds
Definition: sample_step.h:584
Parent::Get_upper_bounds Get_upper_bounds
Definition: sample_step.h:1077
virtual const Get_dimension & get_dimension_function() const =0
Returns a reference to the mechanism for computing the dimension of the model.
virtual const Get_dimension & get_dimension_function() const
Returns a reference to a function that is used to obtain the dimension of the model. See Model_dimension for more info.
Definition: sample_step.h:519
Model_parameter_evaluator< Model >::Type Get_step_size
Definition: sample_step.h:578
void set_post_move_callback(const boost::function2< void, Model &, kjb::Vector & > &f)
Copy-constructor.
Definition: sample_step.h:1190
void swap(Perspective_camera &cam1, Perspective_camera &cam2)
Swap two cameras.
Definition: perspective_camera.h:599
Model_evaluator< Model >::Type Target_distribution
Definition: sample_step.h:53
Model_dimension< Model >::Type Get_dimension
Definition: sample_step.h:385
Definition: sample_step.h:1062
std::map< std::string, double > extra
Definition: sample_base.h:105
boost::function2< boost::optional< double >, Model &, size_t > Type
Definition: sample_base.h:426
r
Definition: APPgetLargeConnectedEdges.m:127
Definition: sample_step.h:219
Structure for returning results of a single sampling move.
Definition: sample_base.h:55
Abstract_hmc_step(const Abstract_hmc_step &ahs)
Definition: sample_step.h:667
virtual const Get_lower_bounds & get_lower_bounds_function() const =0
Returns a reference to the mechanism for getting the lower bounds of a function.
Get_dimension m_get_dimension
Definition: sample_step.h:526
Definition: sample_base.h:160
This class implements vectors, in the linear-algebra sense, with real-valued elements.
Definition: m_vector.h:87
bool no_change
proposal didn't modify the model
Definition: sample_base.h:386
virtual const Get_upper_bounds & get_upper_bounds_function() const
Returns a reference to the mechanism for getting the upper bounds of a function.
Definition: sample_step.h:1218
double m_alpha
Amount of stochastic update to apply to momentum. Set to zero for strict HMC.
Definition: sample_step.h:783
Basic_mh_step(const Target_distribution &log_target, const Proposer_type &proposer)
Initializes target and proposer functors (or functions) to the given arguments.
Definition: sample_step.h:237
double rev_prob
log reverse proposal probability
Definition: sample_base.h:381
Vector sample(const MV_gaussian_distribution &dist)
Sample from a multivariate normal distribution.
Definition: prob_sample.cpp:42
double m_temperature
Definition: sample_step.h:796
virtual const Get_parameter & get_parameter_function() const =0
Returns a reference to the mechanism for getting the value of a dimension of the model.
virtual void post_move_callback(Model &q, kjb::Vector &p) const
Definition: sample_step.h:1220
Parent::Move_parameter Move_parameter
Definition: sample_step.h:1070
void set_temperature(double T)
Definition: sample_step.h:333
void set_temperature(const double T)
Definition: sample_step.h:729
Parent::Get_step_size Get_step_size
Definition: sample_step.h:1071
BOOST_CONCEPT_ASSERT((BaseModel< Model >))
virtual const Proposer & get_proposer() const =0
Returns a reference to the proposal mechanism. Returned object must comply with the GibbsModelPropose...
virtual const Get_lower_bounds & get_lower_bounds_function() const
Returns a reference to the mechanism for getting the lower bounds of a function.
Definition: sample_step.h:1216
virtual const Get_step_size & get_step_size_function() const =0
Returns a reference to the mechanism for choosing the neighborhoods for each parameters.
virtual ~Basic_gibbs_step()
Definition: sample_step.h:521
kjb::Vector p
Momentum.
Definition: sample_step.h:788
Target_distribution m_log_target
Definition: sample_step.h:354
Move_parameter m_move_parameter
Definition: sample_step.h:1229
virtual Step_log< Model > operator()(Model &m, double lt_m) const
Runs a step of Metropolis-Hastings on a model m.
Definition: sample_step.h:198
bool m_first_p_full
Optimization constants. Set to false for true MCMC.
Definition: sample_step.h:793
bool m_last_p_ignore
Definition: sample_step.h:794
virtual const Move_parameter & get_move_parameter() const
Returns a reference to the parameter-changing mechanism. Must comply with the ChangeParameter concept...
Definition: sample_step.h:1201
iterator end()
Definition: m_vector.h:557
Get_model_parameter< Model >::Type Get_parameter
Definition: sample_step.h:582
Definition: sample_step.h:1252
Target_distribution m_log_target
Definition: sample_step.h:524
iterator begin()
Definition: m_vector.h:537
Basic_hmc_step< Model, false, false, REVERSIBLE > Type
Definition: sample_step.h:1254
Abstract_gibbs_step< Model > Parent
Definition: sample_step.h:463
Abstract_hmc_step(int num_dynamics_steps, double alpha)
Definition: sample_step.h:588
Abstract_hmc_step< Model, CONSTRAINED_TARGET, INCLUDE_ACCEPT_STEP, REVERSIBLE > Parent
Definition: sample_step.h:1066
boost::optional< Model > tmp_model_
Definition: sample_step.h:114
Parent::Get_parameter Get_parameter
Definition: sample_step.h:1075
Model_dimension< Model >::Type Get_dimension
Definition: sample_step.h:579
Multivariate Gaussian (normal) distribution.
Definition: prob_distribution.h:619
bool is_first_p_full(const bool alpha, const bool accept_step, const bool reversible)
Definition: sample_step.h:598
bool m_record_extra
Definition: sample_step.h:1233
boost::function1< double, const Model & > Type
Definition: sample_base.h:214
void record_extra(bool enable)
Definition: sample_step.h:1155
virtual const Target_distribution & get_log_target() const =0
Returns a reference to the target distribution. Returned object must comply with the ModelEvaluator c...
Definition: sample_step.h:572
Get_upper_bounds m_get_upper_bounds
Definition: sample_step.h:1238
Move_model_parameter< Model >::Type Move_parameter
Definition: sample_step.h:577
virtual bool record_extra() const
if true is returned, the step log will contain metadata about the step
Definition: sample_step.h:1208
boost::function1< kjb::Vector, const Model & > Type
Definition: sample_base.h:317
Model_evaluator< Model >::Type Target_distribution
Definition: sample_step.h:575
void swap(kjb::Gsl_Multimin_fdf &m1, kjb::Gsl_Multimin_fdf &m2)
Swap two wrapped multimin objects.
Definition: gsl_multimin.h:693
boost::function3< void, Model &, size_t, double > Type
Definition: sample_base.h:294
Parent::Get_dimension Get_dimension
Definition: sample_step.h:467
virtual Mh_proposal_result propose(const Model &m, Model &m_p) const =0
Propose a new model.
Get_lower_bounds m_get_lower_bounds
Definition: sample_step.h:1237
Get_dimension m_get_dimension
Definition: sample_step.h:1231
Parent::Target_distribution Target_distribution
Definition: sample_step.h:465
virtual double get_temperature() const
Definition: sample_step.h:90
Proposer m_proposer
Definition: sample_step.h:525
Definition: sample_step.h:50
Gibbs_model_proposer< Model >::Type Proposer
Definition: sample_step.h:384
Sampling functionality for the different distributions defined in "prob_distributions.h".
Parent::Gradient Gradient
Definition: sample_step.h:1069
virtual const Gradient & get_gradient() const =0
Returns a reference to the mechanism to compute the gradient of the target distribution.
std::string type
Name of proposal type.
Definition: sample_base.h:383
virtual void post_move_callback(Model &, kjb::Vector &) const
Definition: sample_step.h:762
Basic_gibbs_step(const Target_distribution &log_target, const Proposer &proposer, const Get_dimension &get_dimension)
Initializes target and proposer functors (or functions) to the given arguments.
Definition: sample_step.h:480
virtual const Get_dimension & get_dimension_function() const =0
Returns a reference to a function that is used to obtain the dimension of the model. See Model_dimension for more info.
Target_distribution m_log_target
Definition: sample_step.h:1227
virtual Step_log< Model > operator()(Model &q, double lt_q) const
Runs a step of Hybrid Monte-Carlo (HMC) on a model m.
Definition: sample_step.h:803
double m_temperature
Definition: sample_step.h:356
Parent::Target_distribution Target_distribution
Definition: sample_step.h:1068
Parent::Target_distribution Target_distribution
Definition: sample_step.h:224
Step_log< Model > run_step(Model &m, double lt_m, double &accept_prob, boost::optional< Model & > proposed_state_out=boost::none) const
Runs a step of Metropolis-Hastings on a model m.
Definition: sample_step.h:120
Proposer_type m_proposer
Definition: sample_step.h:355
get the indices of edges in each direction for i
Definition: APPgetLargeConnectedEdges.m:48
bool m_record_extra
Definition: sample_step.h:358
boost::math::uniform Uniform_distribution
Definition: prob_distribution.h:70
for m
Definition: APPgetLargeConnectedEdges.m:64
Abstract_mh_step< Model, Proposer_type > Parent
Definition: sample_step.h:222
Support for error handling exception classes in libKJB.
Parent::Get_dimension Get_dimension
Definition: sample_step.h:1072
boost::function2< double, const Model &, size_t > Type
Definition: sample_base.h:270
virtual double l_target(const Model &m) const =0
Evaluate the log-target distribution for the given model.
Definition: sample_concept.h:41
Value_type magnitude_squared() const
Return this vector's squared magnitude.
Definition: m_vector.h:1501
virtual const Target_distribution & get_log_target() const =0
Returns a reference to the target distribution. Returned object must comply with the ModelEvaluator c...
virtual ~Abstract_gibbs_step()
Definition: sample_step.h:417
Model_parameter_evaluator< Model >::Type Gradient
Definition: sample_step.h:576
Basic_hmc_step(const Target_distribution &log_target, int num_dynamics_steps, const Gradient &gradient, const Move_parameter &move_parameter, const Get_step_size &get_step_size, const Get_dimension &get_dimension, double alpha=0.0)
Creates a Basic_hmc_step by initializing target and proposer functors (or functions) to the given arg...
Definition: sample_step.h:1106
void record_extra(bool enable)
Definition: sample_step.h:324
BOOST_CONCEPT_ASSERT((BaseModel< Model >))
virtual ~Abstract_mh_step()
Definition: sample_step.h:92
virtual const Get_step_size & get_step_size_function() const
Returns a reference to the mechanism for choosing the neighborhoods for each parameters.
Definition: sample_step.h:1203
Model_parameter_evaluator< Model >::Type Get_lower_bounds
Definition: sample_step.h:583
boost::function1< size_t, const Model & > Type
Definition: sample_base.h:305
virtual double l_target(const Model &m) const
Evaluate the log-target distribution for the given model.
Definition: sample_step.h:301
virtual bool record_extra() const
Definition: sample_step.h:344
Gradient m_gradient
Definition: sample_step.h:1228
Get_step_size m_get_step_size
Definition: sample_step.h:1230
virtual ~Basic_mh_step()
Initializes target and proposer functors (or functions) to the given arguments.
Definition: sample_step.h:277
virtual double get_temperature() const
Definition: sample_step.h:338
virtual const Proposer & get_proposer() const
Returns a reference to the proposal mechanism. Returned object must comply with the GibbsModelPropose...
Definition: sample_step.h:517
virtual ~Abstract_hmc_step()
Definition: sample_step.h:768
virtual ~Basic_hmc_step()
Definition: sample_step.h:1195
Definition: sample_step.h:380
virtual const Gradient & get_gradient() const
Returns a reference to the mechanism to compute the gradient of the target distribution.
Definition: sample_step.h:1199