KJB
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sample_vector.h
Go to the documentation of this file.
1 /* $Id: sample_vector.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: Ernesto Brau
18  * =========================================================================== */
19 
20 #ifndef SAMPLE_VECTOR_H_INCLUDED
21 #define SAMPLE_VECTOR_H_INCLUDED
22 
23 #include <algorithm>
24 #include "sample_cpp/sample_step.h"
26 
27 #include <wrap_lapack/wrap_lapack.h>
29 #include <m_cpp/m_matrix.h>
30 #include <n_cpp/n_cholesky.h>
31 
36 template<class Model>
37 inline
38 double get_vector_model_parameter(const Model& m, int i)
39 {
40  return m[i];
41 }
42 
47 template<class Model>
48 inline
49 void set_vector_model_parameter(Model& m, int i, double x)
50 {
51  m[i] = x;
52 }
53 
59 template<class Model>
60 inline
61 void move_vector_model_parameter(Model& m, int i, double x)
62 {
63  Move_model_parameter_as_plus<Model> mmpap(set_vector_model_parameter<Model>,
64  get_vector_model_parameter<Model>);
65  mmpap(m, i, x);
66 }
67 
68 
73 template<class Model>
74 inline
75 int get_vector_model_dimension(const Model& m)
76 {
77  return m.size();
78 }
79 
85 template<typename Model>
87 {
88 public:
90 
93 
103  (
104  const Target_distribution& log_target,
105  const Get_neighborhood& get_neighborhood
106  ) :
107  Parent
108  (
109  log_target,
110  move_vector_model_parameter<Model>,
111  get_neighborhood,
112  get_vector_model_dimension<Model>
113  )
114  {}
115 };
116 
127 template<typename Model, bool CONSTRAIN_TARGET = false, bool INCLUDE_ACCEPT_STEP = true, bool REVERSIBLE = true>
128 class Vector_hmc_step : public Basic_hmc_step<Model, CONSTRAIN_TARGET, INCLUDE_ACCEPT_STEP, REVERSIBLE>
129 {
130 public:
132 
134  typedef typename Parent::Gradient Gradient;
138 
155  (
156  const Target_distribution& log_target,
157  int num_dynamics_steps,
158  const Gradient& gradient,
159  const Get_step_size& get_step_size,
160  double alpha = 0.0
161  ) :
162  Parent(log_target,
163  num_dynamics_steps,
164  gradient,
165  move_vector_model_parameter<Model>,
166  get_step_size,
167  get_vector_model_dimension<Model>,
168  alpha)
169  {}
170 
172  (
173  const Target_distribution& log_target,
174  int num_dynamics_steps,
175  const Gradient& gradient,
176  const Get_step_size& get_step_size,
177  const Get_lower_bounds& get_lower_bounds,
178  const Get_upper_bounds& get_upper_bounds,
179  double alpha = 0.0
180  ) :
181  Parent(log_target,
182  num_dynamics_steps,
183  gradient,
184  move_vector_model_parameter<Model>,
185  get_step_size,
186  get_vector_model_dimension<Model>,
187  get_vector_model_parameter<Model>,
188  get_lower_bounds,
189  get_upper_bounds,
190  alpha)
191  {}
192 
194  {}
195 };
196 
207 template<class Model, bool REVERSIBLE = true>
209 {
211 };
212 
213 template<typename SimpleVector>
215 {
216 private:
217  kjb::Vector scale_;
218 
220  Independent_gaussian_proposer(const kjb::Vector& covariance) :
221  scale_(covariance.size())
222  {
223  std::transform(covariance.begin(), covariance.end(), scale_.begin(), static_cast<double(*)(double)>(sqrt));
224  }
225 
227  Mh_proposal_result operator()(const SimpleVector& m, SimpleVector& mp) const
228  {
229  if(m.size() != scale_.size())
230  {
232  }
233 
234  mp.resize(m.size());
235  for(size_t i = 0; i < mp.size(); ++i)
236  {
237  mp[i] = m[i] + kjb::sample(kjb::STD_NORMAL) * scale_[i];
238  }
239 
240  return Mh_proposal_result();
241  }
242 };
243 
250 template<typename VectorModel>
252 {
253 private:
254  typedef Mv_gaussian_proposer Self;
255  kjb::Matrix chol_cov_;
256  double log_lambda_;
257  double sqrt_t_;
258 
259 public:
261  Mv_gaussian_proposer(const kjb::Matrix& covariance) :
262  chol_cov_(kjb::cholesky_decomposition(covariance)),
263  log_lambda_(0.0),
264  sqrt_t_(1.0)
265  {}
266 
267  void set_temperature(double t)
268  {
269  sqrt_t_ = sqrt(t);
270  }
271 
274  {
275  size_t N = m.size();
276  if(N != chol_cov_.get_num_rows() ||
277  N != mp.size())
278  {
280  }
281 
282  kjb::Vector delta(N);
283  std::generate(delta.begin(), delta.end(), boost::bind(Self::gauss_sample_));
284  // scale by temperature, global scale, and covariance matrix
285  delta = sqrt_t_ * exp(log_lambda_/2.0) * chol_cov_ * delta;
286 
287  std::transform(
288  m.begin(),
289  m.end(),
290  delta.begin(),
291  mp.begin(),
292  std::plus<double>());
293 
294  return Mh_proposal_result();
295  }
296 
301  {
302  return chol_cov_;
303  }
304 
306  {
307  kjb::Matrix result = sqrt_t_ * exp(log_lambda_/2.0) * chol_cov_;
308  result = result.transpose() * result;
309  return result;
310  }
311 
315  double get_global_scale() const
316  {
317  return sqrt(exp(log_lambda_));
318  }
319 
332  template <class VectorType>
333  void adapt_covariance(const VectorType& delta, double gamma)
334  {
335 #ifdef TEST
336 // kjb::Matrix ref = chol_cov_;
337 // kjb::Matrix test = chol_cov_;
338 #endif
339 
340  rank_1_update_2(chol_cov_, delta, gamma);
341 
342 #ifdef TEST
343  // try rank-one update a few different ways, to see if they're all equivalent
344 //
345 // double diff;
346 // rank_1_update_ref(ref, delta, gamma);
347 // diff = max_abs_difference(chol_cov_,ref);
348 // assert(diff < FLT_EPSILON);
349 //
356 // assert(diff < FLT_EPSILON);
357 #endif /* TEST */
358 
359  }
360 
370  void adapt_global_scale(double x)
371  {
372  log_lambda_ += x;
373  }
374 
378  void rank_1_update(kjb::Matrix& C, const VectorModel& delta, double gamma)
379  {
380 #ifdef KJB_HAVE_LAPACK
381  int N = delta.size();
382  kjb::Matrix tmp(N, 1);
383  std::copy(delta.begin(), delta.end(), &tmp(0,0));
384  lapack_solve_triangular(
385  C.get_c_matrix(),
386  tmp.get_c_matrix(),
388 
389  tmp = tmp * tmp.transpose();
390 
391  // M -= I
392  for(size_t i = 0; i < N; ++i)
393  tmp(i,i) -= 1.0;
394 
395  lower_triangular_product_(C, tmp, tmp);
396  tmp *= gamma;
397  C += tmp;
398 #else
400 #endif
401  }
402 
406  void rank_1_update_2(kjb::Matrix& C, const VectorModel& delta, double gamma)
407  {
408  // TODO: DEBUG ME
409  // I'm failing when gamma == 1.
410  // Questions to answer:
411  // why am I multiplying C by sqrt(1-gamma)?
412  // check rasmussen's adaptive mh paper
413  VectorModel x = sqrt(gamma) * delta;
414  size_t N = delta.size();
415 
416  C *= sqrt(1-gamma);
417 
418  for(size_t k = 0; k < N; ++k)
419  {
420  double& C_k = C(k,k);
421  const double x_k = x[k];
422 
423  double r = sqrt(C_k*C_k+x_k * x_k);
424  double c = r/C_k;
425  double s = x_k/C_k;
426  C_k = r;
427  for(size_t k2 = k+1; k2 < N; ++k2)
428  {
429  C(k2,k) = (C(k2,k) + s*x[k2])/c;
430  x[k2] = c*x[k2] - s*C(k2, k);
431  }
432  }
433  }
434 
435 
439  void rank_1_update_ref(kjb::Matrix& C, const VectorModel& delta, double gamma)
440  {
441  kjb::Vector tmp(delta.begin(), delta.end());
442  C = C * C.transpose();
443  C += gamma * (kjb::outer_product(tmp, tmp)-C);
444 #ifdef TEST
445  kjb::Matrix m_tmp = C;
446 #endif
447 
449 
450 #ifdef TEST
451  assert(kjb::max_abs_difference(C * C.transpose(), m_tmp) < FLT_EPSILON);
452 #endif
453  }
454 
455 private:
456  // utility
457  static double gauss_sample_() { return kjb::sample(kjb::STD_NORMAL); }
458 
463  void lower_triangular_product_(
464  const kjb::Matrix& op1,
465  const kjb::Matrix& op2,
466  kjb::Matrix& out)
467  {
468  const size_t N = op1.get_num_cols();
469  kjb::Matrix tmp(N,N, 0.0);
470 
471  for(size_t r = 0; r < N; ++r)
472  for(size_t c = 0; c <= r; ++c)
473  for(size_t i = c; i <= r; ++i)
474  tmp(r,c) += op1(r,i)*op2(i,c);
475  out.swap(tmp);
476  }
477 };
478 
492 template<typename VectorModel>
493 class Vector_srw_step : public Basic_mh_step<VectorModel, Mv_gaussian_proposer<VectorModel> >
494 {
495 public:
498 
500  typedef typename Base::Proposer Proposer;
501 
510  (
511  const Target_distribution& target,
512  const kjb::Matrix& covariance
513  ) :
514  Base(target,
515  Proposer(covariance))
516  {}
517 
526  (
527  const Target_distribution& target,
528  const kjb::Vector& covariance
529  ) :
530  Base(target,
531  Proposer(covariance))
532  {}
533 
537  inline void set_covariance(const kjb::Matrix& covariance)
538  {
539  Proposer& proposer = Base::get_proposer_();
540  proposer = Mv_gaussian_proposer<VectorModel>(covariance);
541  }
542 
543  inline void set_covariance(const kjb::Vector& covariance)
544  {
545  Proposer& proposer = Base::get_proposer_();
546  proposer = Mv_gaussian_proposer<VectorModel>(covariance);
547  }
548 
550  {}
551 };
552 
553 #endif /*SAMPLE_VECTOR_H_INCLUDED */
554 
virtual ~Vector_hmc_step()
Definition: sample_vector.h:193
Mv_gaussian_proposer< VectorModel > & get_proposer_()
Definition: sample_step.h:349
Parent::Get_lower_bounds Get_lower_bounds
Definition: sample_step.h:1076
Parent::Get_lower_bounds Get_lower_bounds
Definition: sample_vector.h:136
Matrix cholesky_decomposition(const Matrix &M)
Definition: n_cholesky.h:35
void rank_1_update(kjb::Matrix &C, const VectorModel &delta, double gamma)
Definition: sample_vector.h:378
Basic_hmc_step< Model, CONSTRAIN_TARGET, INCLUDE_ACCEPT_STEP, REVERSIBLE > Parent
Definition: sample_vector.h:131
Definition: sample_vector.h:208
Definition for the Matrix class, a thin wrapper on the KJB Matrix struct and its related functionalit...
Basic_mh_step< VectorModel, Mv_gaussian_proposer< VectorModel > > Base
Definition: sample_vector.h:496
size_type size() const
Alias to get_length(). Required to comply with stl Container concept.
Definition: m_vector.h:510
kjb::Matrix get_covariance() const
Definition: sample_vector.h:305
void adapt_covariance(const VectorType &delta, double gamma)
Definition: sample_vector.h:333
Definition of various standard probability distributions.
const kjb::Matrix & get_unscaled_cholesky_covariance() const
Definition: sample_vector.h:300
Mh_proposal_result operator()(const VectorModel &m, VectorModel &mp) const
Propose a new value.
Definition: sample_vector.h:273
Indicates the result of an MH proposal. It is simply a pair of probabilities, forward and backward...
Definition: sample_base.h:334
Base::Proposer Proposer
Definition: sample_vector.h:500
Object thrown when an argument is of the wrong size or dimensions.
Definition: l_exception.h:426
Definition: sample_vector.h:251
Definition: sample_concept.h:73
int get_num_rows() const
Return the number of rows in the matrix.
Definition: m_matrix.h:543
Impl_type *& get_underlying_representation_with_guilt()
Get pointer to the underlying kjb_c::Matrix C struct.
Definition: m_matrix.h:591
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
void set_temperature(double t)
Definition: sample_vector.h:267
Parent::Get_step_size Get_step_size
Definition: sample_vector.h:135
Int_matrix::Value_type max_abs_difference(const Int_matrix &op1, const Int_matrix &op2)
Find the largest difference between two matrices.
Definition: l_int_matrix.h:1364
Model_parameter_evaluator< Model >::Type Get_step_size
Definition: sample_step.h:578
Parent::Target_distribution Target_distribution
Definition: sample_vector.h:133
Definition: sample_step.h:1062
virtual ~Vector_srw_step()
Definition: sample_vector.h:549
for k
Definition: APPgetLargeConnectedEdges.m:61
Definition: sample_vector.h:493
Vector_numerical_gradient(const Target_distribution &log_target, const Get_neighborhood &get_neighborhood)
Construct this functor.
Definition: sample_vector.h:103
r
Definition: APPgetLargeConnectedEdges.m:127
Definition: sample_step.h:219
#define KJB_THROW(ex)
Definition: l_exception.h:46
Vector_srw_step Self
Definition: sample_vector.h:497
Matrix outer_product(const Vector &v1, const Vector &v2)
Definition: m_matrix.h:2293
This class implements vectors, in the linear-algebra sense, with real-valued elements.
Definition: m_vector.h:87
Vector sample(const MV_gaussian_distribution &dist)
Sample from a multivariate normal distribution.
Definition: prob_sample.cpp:42
double get_vector_model_parameter(const Model &m, int i)
Parameter getter for anything that implements operator[].
Definition: sample_vector.h:38
Definition: sample_vector.h:128
Base::Target_distribution Target_distribution
Definition: sample_vector.h:499
Definition: sample_vector.h:214
Parent::Gradient Gradient
Definition: sample_vector.h:134
Parent::Get_step_size Get_step_size
Definition: sample_step.h:1071
int get_num_cols() const
Return the number of columns in the matrix.
Definition: m_matrix.h:554
iterator end()
Definition: m_vector.h:557
Model_parameter_evaluator< Model >::Type Get_neighborhood
Definition: sample_default.h:104
iterator begin()
Definition: m_vector.h:537
Default move function; uses '+'.
Definition: sample_default.h:37
x
Definition: APPgetLargeConnectedEdges.m:100
Model_evaluator< Model >::Type Target_distribution
Definition: sample_default.h:102
const Gaussian_distribution STD_NORMAL
Definition: prob_distribution.cpp:12
void move_vector_model_parameter(Model &m, int i, double x)
Parameter mover for anything that implements operator[] and whose elements are double.
Definition: sample_vector.h:61
void set_vector_model_parameter(Model &m, int i, double x)
Parameter setter for anything that implements operator[].
Definition: sample_vector.h:49
#define KJB_THROW_2(ex, msg)
Definition: l_exception.h:48
int get_vector_model_dimension(const Model &m)
Dimension for any model that implements the size() member function.
Definition: sample_vector.h:75
Model_evaluator< Model >::Type Target_distribution
Definition: sample_step.h:575
Matrix transpose() const
Transpose this matrix.
Definition: m_matrix.cpp:395
void rank_1_update_2(kjb::Matrix &C, const VectorModel &delta, double gamma)
Definition: sample_vector.h:406
Numerical_gradient< Model > Parent
Definition: sample_vector.h:89
Mv_gaussian_proposer(const kjb::Matrix &covariance)
Construct a Mv_gaussian_proposer.
Definition: sample_vector.h:261
Vector_hmc_step< Model, false, REVERSIBLE > Type
Definition: sample_vector.h:210
Parent::Target_distribution Target_distribution
Definition: sample_step.h:1068
Parent::Target_distribution Target_distribution
Definition: sample_step.h:224
const Impl_type * get_c_matrix() const
Get const pointer to the underlying kjb_c::Matrix C struct.
Definition: m_matrix.h:601
Parent::Get_upper_bounds Get_upper_bounds
Definition: sample_vector.h:137
get the indices of edges in each direction for i
Definition: APPgetLargeConnectedEdges.m:48
void rank_1_update_ref(kjb::Matrix &C, const VectorModel &delta, double gamma)
Definition: sample_vector.h:439
void adapt_global_scale(double x)
Definition: sample_vector.h:370
This class implements matrices, in the linear-algebra sense, with real-valued elements.
Definition: m_matrix.h:94
Vector_hmc_step(const Target_distribution &log_target, int num_dynamics_steps, const Gradient &gradient, const Get_step_size &get_step_size, double alpha=0.0)
Creates a Vector_hmc_step.
Definition: sample_vector.h:155
for m
Definition: APPgetLargeConnectedEdges.m:64
double get_global_scale() const
Definition: sample_vector.h:315
Object thrown when a program lacks required resources or libraries.
Definition: l_exception.h:539
void swap(Matrix &other)
Swap the representations of two matrices.
Definition: m_matrix.h:532
Parent::Target_distribution Target_distribution
Definition: sample_vector.h:91
void set_covariance(const kjb::Vector &covariance)
Definition: sample_vector.h:543
void set_covariance(const kjb::Matrix &covariance)
Definition: sample_vector.h:537
Model_parameter_evaluator< Model >::Type Gradient
Definition: sample_step.h:576
Parent::Get_neighborhood Get_neighborhood
Definition: sample_vector.h:92
Model_parameter_evaluator< Model >::Type Get_lower_bounds
Definition: sample_step.h:583
Vector_srw_step(const Target_distribution &target, const kjb::Matrix &covariance)
Creates a Vector_srw_step.
Definition: sample_vector.h:510
Approximates the gradient of a target distribution, evaluated at a certain location. The model in question must be a vector model.
Definition: sample_vector.h:86
Approximates the gradient and/or curvature of a target distribution, evaluated at a certain location...
Definition: sample_default.h:99