Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
lbfgs_update.hpp
Go to the documentation of this file.
1 #ifndef STAN__OPTIMIZATION__LBFGS_UPDATE_HPP
2 #define STAN__OPTIMIZATION__LBFGS_UPDATE_HPP
3 
4 #include <vector>
5 
6 #include <boost/tuple/tuple.hpp>
7 #include <boost/circular_buffer.hpp>
8 
10 
11 namespace stan {
12  namespace optimization {
18  template<typename Scalar = double,
19  int DimAtCompile = Eigen::Dynamic>
20  class LBFGSUpdate {
21  public:
22  typedef Eigen::Matrix<Scalar,DimAtCompile,1> VectorT;
23  typedef Eigen::Matrix<Scalar,DimAtCompile,DimAtCompile> HessianT;
24  typedef boost::tuple<Scalar,VectorT,VectorT> UpdateT;
25 
26  LBFGSUpdate(size_t L = 5) : _buf(L) {}
27 
33  void set_history_size(size_t L) {
34  _buf.rset_capacity(L);
35  }
36 
48  inline Scalar update(const VectorT &yk, const VectorT &sk,
49  bool reset = false) {
50  Scalar skyk = yk.dot(sk);
51 
52  Scalar B0fact;
53  if (reset) {
54  B0fact = yk.squaredNorm()/skyk;
55  _buf.clear();
56  }
57  else {
58  B0fact = 1.0;
59  }
60 
61  // New updates are pushed to the "back" of the circular buffer
62  Scalar invskyk = 1.0/skyk;
63  _gammak = skyk/yk.squaredNorm();
64  _buf.push_back();
65  _buf.back() = boost::tie(invskyk,yk,sk);
66 
67  return B0fact;
68  }
69 
78  inline void search_direction(VectorT &pk, const VectorT &gk) const {
79  std::vector<Scalar> alphas(_buf.size());
80  typename boost::circular_buffer<UpdateT>::const_reverse_iterator buf_rit;
81  typename boost::circular_buffer<UpdateT>::const_iterator buf_it;
82  typename std::vector<Scalar>::const_iterator alpha_it;
83  typename std::vector<Scalar>::reverse_iterator alpha_rit;
84 
85  pk.noalias() = -gk;
86  for (buf_rit = _buf.rbegin(), alpha_rit = alphas.rbegin();
87  buf_rit != _buf.rend();
88  buf_rit++, alpha_rit++) {
89  Scalar alpha;
90  const Scalar &rhoi(boost::get<0>(*buf_rit));
91  const VectorT &yi(boost::get<1>(*buf_rit));
92  const VectorT &si(boost::get<2>(*buf_rit));
93 
94  alpha = rhoi * si.dot(pk);
95  pk -= alpha * yi;
96  *alpha_rit = alpha;
97  }
98  pk *= _gammak;
99  for (buf_it = _buf.begin(), alpha_it = alphas.begin();
100  buf_it != _buf.end();
101  buf_it++, alpha_it++) {
102  Scalar beta;
103  const Scalar &rhoi(boost::get<0>(*buf_it));
104  const VectorT &yi(boost::get<1>(*buf_it));
105  const VectorT &si(boost::get<2>(*buf_it));
106 
107  beta = rhoi*yi.dot(pk);
108  pk += (*alpha_it - beta)*si;
109  }
110  }
111 
112  protected:
113  boost::circular_buffer<UpdateT> _buf;
114  Scalar _gammak;
115  };
116  }
117 }
118 
119 #endif
void search_direction(VectorT &pk, const VectorT &gk) const
Compute the search direction based on the current (inverse) Hessian approximation and given gradient...
Eigen::Matrix< Scalar, DimAtCompile, DimAtCompile > HessianT
Scalar update(const VectorT &yk, const VectorT &sk, bool reset=false)
Add a new set of update vectors to the history.
boost::circular_buffer< UpdateT > _buf
void set_history_size(size_t L)
Set the number of inverse Hessian updates to keep.
boost::tuple< Scalar, VectorT, VectorT > UpdateT
Eigen::Matrix< Scalar, DimAtCompile, 1 > VectorT
Implement a limited memory version of the BFGS update.

     [ Stan Home Page ] © 2011–2014, Stan Development Team.