/** * Compute the search direction based on the current (inverse) Hessian * approximation and given gradient. * * @param[out] pk The negative product of the inverse Hessian and gradient * direction gk. * @param[in] gk Gradient direction. **/ inline void search_direction(VectorT &pk, const VectorT &gk) const { std::vector<Scalar> alphas(_buf.size()); typename boost::circular_buffer<UpdateT>::const_reverse_iterator buf_rit; typename boost::circular_buffer<UpdateT>::const_iterator buf_it; typename std::vector<Scalar>::const_iterator alpha_it; typename std::vector<Scalar>::reverse_iterator alpha_rit; pk.noalias() = -gk; for (buf_rit = _buf.rbegin(), alpha_rit = alphas.rbegin(); buf_rit != _buf.rend(); buf_rit++, alpha_rit++) { Scalar alpha; const Scalar &rhoi(boost::get<0>(*buf_rit)); const VectorT &yi(boost::get<1>(*buf_rit)); const VectorT &si(boost::get<2>(*buf_rit)); alpha = rhoi * si.dot(pk); pk -= alpha * yi; *alpha_rit = alpha; } pk *= _gammak; for (buf_it = _buf.begin(), alpha_it = alphas.begin(); buf_it != _buf.end(); buf_it++, alpha_it++) { Scalar beta; const Scalar &rhoi(boost::get<0>(*buf_it)); const VectorT &yi(boost::get<1>(*buf_it)); const VectorT &si(boost::get<2>(*buf_it)); beta = rhoi*yi.dot(pk); pk += (*alpha_it - beta)*si; } }