1 #ifndef STAN__OPTIMIZATION__BFGS_LINESEARCH_HPP
2 #define STAN__OPTIMIZATION__BFGS_LINESEARCH_HPP
9 #include <boost/math/special_functions/fpclassify.hpp>
12 namespace optimization {
34 template<
typename Scalar>
36 const Scalar &x1,
const Scalar &f1,
const Scalar &df1,
37 const Scalar &loX,
const Scalar &hiX)
39 const Scalar c3((-12*f1 + 6*x1*(df0 + df1))/(x1*x1*x1));
40 const Scalar c2(-(4*df0 + 2*df1)/x1 + 6*f1/(x1*x1));
41 const Scalar &c1(df0);
43 const Scalar t_s =
std::sqrt(c2*c2 - 2.0*c1*c3);
44 const Scalar s1 = - (c2 + t_s)/c3;
45 const Scalar s2 = - (c2 - t_s)/c3;
51 minF = loX*(loX*(loX*c3/3.0 + c2)/2.0 + c1);
55 tmpF = hiX*(hiX*(hiX*c3/3.0 + c2)/2.0 + c1);
62 if (loX < s1 && s1 < hiX) {
63 tmpF = s1*(s1*(s1*c3/3.0 + c2)/2.0 + c1);
71 if (loX < s2 && s2 < hiX) {
72 tmpF = s2*(s2*(s2*c3/3.0 + c2)/2.0 + c1);
103 template<
typename Scalar>
104 Scalar
CubicInterp(
const Scalar &x0,
const Scalar &f0,
const Scalar &df0,
105 const Scalar &x1,
const Scalar &f1,
const Scalar &df1,
106 const Scalar &loX,
const Scalar &hiX)
108 return x0 +
CubicInterp(df0,x1-x0,f1-f0,df1,loX-x0,hiX-x0);
115 template<
typename FunctorType,
typename Scalar,
typename XType>
116 int WolfLSZoom(Scalar &alpha, XType &newX, Scalar &newF, XType &newDF,
118 const XType &x,
const Scalar &f,
const Scalar &dfp,
119 const Scalar &c1dfp,
const Scalar &c2dfp,
const XType &p,
120 Scalar alo, Scalar aloF, Scalar aloDFp,
121 Scalar ahi, Scalar ahiF, Scalar ahiDFp,
122 const Scalar &min_range)
124 Scalar d1, d2, newDFp;
134 alpha = 0.5*(alo+ahi);
138 d1 = aloDFp + ahiDFp - 3*(aloF-ahiF)/(alo-ahi);
142 alpha = ahi - (ahi - alo)*(ahiDFp + d2 - d1)/(ahiDFp - aloDFp + 2*d2);
146 alpha = 0.5*(alo+ahi);
150 while (func(newX,newF,newDF)) {
151 alpha = 0.5*(alpha+
std::min(alo,ahi));
156 newDFp = newDF.dot(p);
157 if (newF > (f + alpha*c1dfp) || newF >= aloF) {
165 if (newDFp*(ahi-alo) >= 0) {
224 template<
typename FunctorType,
typename Scalar,
typename XType>
227 XType &x1, Scalar &f1, XType &gradx1,
229 const XType &x0,
const Scalar &f0,
const XType &gradx0,
230 const Scalar &c1,
const Scalar &c2,
231 const Scalar &minAlpha)
233 const Scalar dfp(gradx0.dot(p));
234 const Scalar c1dfp(c1*dfp);
235 const Scalar c2dfp(c2*dfp);
237 Scalar alpha0(minAlpha);
238 Scalar alpha1(alpha);
241 XType prevDF(gradx0);
245 int retCode = 0, nits = 0, ret;
248 x1.noalias() = x0 + alpha1*p;
249 ret = func(x1,f1,gradx1);
251 alpha1 = 0.5*(alpha0+alpha1);
254 newDFp = gradx1.dot(p);
255 if ((f1 > f0 + alpha*c1dfp) || (f1 >= prevF && nits > 0)) {
256 retCode = WolfLSZoom(alpha, x1, f1, gradx1,
260 alpha0, prevF, prevDFp,
270 retCode = WolfLSZoom(alpha, x1, f1, gradx1,
275 alpha0, prevF, prevDFp,
282 std::swap(prevDF,gradx1);
fvar< T > fabs(const fvar< T > &x)
bool isfinite(const stan::agrad::var &v)
Checks if the given number has finite value.
int WolfeLineSearch(FunctorType &func, Scalar &alpha, XType &x1, Scalar &f1, XType &gradx1, const XType &p, const XType &x0, const Scalar &f0, const XType &gradx0, const Scalar &c1, const Scalar &c2, const Scalar &minAlpha)
Perform a line search which finds an approximate solution to: satisfying the strong Wolfe conditions...
double max(const double a, const double b)
fvar< T > sqrt(const fvar< T > &x)
Scalar CubicInterp(const Scalar &df0, const Scalar &x1, const Scalar &f1, const Scalar &df1, const Scalar &loX, const Scalar &hiX)
Find the minima in an interval [loX, hiX] of a cubic function which interpolates the points...
double e()
Return the base of the natural logarithm.
double min(const double a, const double b)