ROL
ROL_LineSearch.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Rapid Optimization Library (ROL) Package
4//
5// Copyright 2014 NTESS and the ROL contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef ROL_LINESEARCH_H
11#define ROL_LINESEARCH_H
12
17#include "ROL_Ptr.hpp"
18#include "ROL_ParameterList.hpp"
19#include "ROL_Types.hpp"
20#include "ROL_Vector.hpp"
21#include "ROL_Objective.hpp"
23#include "ROL_ScalarFunction.hpp"
24
25namespace ROL {
26
27template<class Real>
29private:
30
33
35 bool usePrevAlpha_; // Use the previous step's accepted alpha as an initial guess
36 Real alpha0_;
37 Real alpha0bnd_; // Lower bound for initial alpha...if below, set initial alpha to one
38 int maxit_;
39 Real c1_;
40 Real c2_;
41 Real c3_;
42 Real eps_;
43 Real fmin_; // smallest fval encountered
44 Real alphaMin_; // Alpha that yields the smallest fval encountered
45 bool acceptMin_; // Use smallest fval if sufficient decrease not satisfied
46 bool itcond_; // true if maximum function evaluations reached
47
48 ROL::Ptr<Vector<Real> > xtst_;
49 ROL::Ptr<Vector<Real> > d_;
50 ROL::Ptr<Vector<Real> > g_;
51 ROL::Ptr<Vector<Real> > grad_;
52// ROL::Ptr<const Vector<Real> > grad_;
53
54public:
55
56
57 virtual ~LineSearch() {}
58
59 // Constructor
60 LineSearch( ROL::ParameterList &parlist ) : eps_(0) {
61 Real one(1), p9(0.9), p6(0.6), p4(0.4), oem4(1.e-4), zero(0);
62 // Enumerations
63 std::string descentName = parlist.sublist("Step").sublist("Line Search").sublist("Descent Method").get("Type","Quasi-Newton Method");
64 edesc_ = StringToEDescent(descentName);
65
66 std::string condName = parlist.sublist("Step").sublist("Line Search").sublist("Curvature Condition").get("Type","Strong Wolfe Conditions");
68 // Linesearch Parameters
69 alpha0_ = parlist.sublist("Step").sublist("Line Search").get("Initial Step Size",one);
70 alpha0bnd_ = parlist.sublist("Step").sublist("Line Search").get("Lower Bound for Initial Step Size",one);
71 useralpha_ = parlist.sublist("Step").sublist("Line Search").get("User Defined Initial Step Size",false);
72 usePrevAlpha_ = parlist.sublist("Step").sublist("Line Search").get("Use Previous Step Length as Initial Guess",false);
73 acceptMin_ = parlist.sublist("Step").sublist("Line Search").get("Accept Linesearch Minimizer",false);
74 maxit_ = parlist.sublist("Step").sublist("Line Search").get("Function Evaluation Limit",20);
75 c1_ = parlist.sublist("Step").sublist("Line Search").get("Sufficient Decrease Tolerance",oem4);
76 c2_ = parlist.sublist("Step").sublist("Line Search").sublist("Curvature Condition").get("General Parameter",p9);
77 c3_ = parlist.sublist("Step").sublist("Line Search").sublist("Curvature Condition").get("Generalized Wolfe Parameter",p6);
78
79 fmin_ = std::numeric_limits<Real>::max();
80 alphaMin_ = 0;
81 itcond_ = false;
82
83 c1_ = ((c1_ < zero) ? oem4 : c1_);
84 c2_ = ((c2_ < zero) ? p9 : c2_);
85 c3_ = ((c3_ < zero) ? p9 : c3_);
86 if ( c2_ <= c1_ ) {
87 c1_ = oem4;
88 c2_ = p9;
89 }
90 if ( edesc_ == DESCENT_NONLINEARCG ) {
91 c2_ = p4;
92 c3_ = std::min(one-c2_,c3_);
93 }
94 }
95
96
97 virtual void initialize( const Vector<Real> &x, const Vector<Real> &s, const Vector<Real> &g,
99 grad_ = g.clone();
100 xtst_ = x.clone();
101 d_ = s.clone();
102 g_ = g.clone();
103 }
104
105 virtual void run( Real &alpha, Real &fval, int &ls_neval, int &ls_ngrad,
106 const Real &gs, const Vector<Real> &s, const Vector<Real> &x,
107 Objective<Real> &obj, BoundConstraint<Real> &con ) = 0;
108
109 // Set epsilon for epsilon active sets
110 void setData(Real &eps, const Vector<Real> &g) {
111 eps_ = eps;
112 grad_->set(g);
113 }
114
115 // use this function to modify alpha and fval if the maximum number of iterations
116 // are reached
117 void setMaxitUpdate(Real &alpha, Real &fnew, const Real &fold) {
118 // Use local minimizer
119 if( itcond_ && acceptMin_ ) {
120 alpha = alphaMin_;
121 fnew = fmin_;
122 }
123 // Take no step
124 else if(itcond_ && !acceptMin_) {
125 alpha = 0;
126 fnew = fold;
127 }
128 setNextInitialAlpha(alpha);
129 }
130
131
132protected:
133 virtual bool status( const ELineSearch type, int &ls_neval, int &ls_ngrad, const Real alpha,
134 const Real fold, const Real sgold, const Real fnew,
135 const Vector<Real> &x, const Vector<Real> &s,
137 Real tol = std::sqrt(ROL_EPSILON<Real>()), one(1), two(2);
138
139 // Check Armijo Condition
140 bool armijo = false;
141 if ( con.isActivated() ) {
142 Real gs(0);
143 if ( edesc_ == DESCENT_STEEPEST ) {
144 updateIterate(*d_,x,s,alpha,con);
145 d_->scale(-one);
146 d_->plus(x);
147 gs = -s.dot(*d_);
148 }
149 else {
150 d_->set(s);
151 d_->scale(-one);
152 con.pruneActive(*d_,grad_->dual(),x,eps_);
153 gs = alpha*(grad_)->dot(d_->dual());
154 d_->zero();
155 updateIterate(*d_,x,s,alpha,con);
156 d_->scale(-one);
157 d_->plus(x);
158 con.pruneInactive(*d_,grad_->dual(),x,eps_);
159 gs += d_->dot(grad_->dual());
160 }
161 if ( fnew <= fold - c1_*gs ) {
162 armijo = true;
163 }
164 }
165 else {
166 if ( fnew <= fold + c1_*alpha*sgold ) {
167 armijo = true;
168 }
169 }
170
171 // Check Maximum Iteration
172 itcond_ = false;
173 if ( ls_neval >= maxit_ ) {
174 itcond_ = true;
175 }
176
177 // Check Curvature Condition
178 bool curvcond = false;
179 if ( armijo && ((type != LINESEARCH_BACKTRACKING && type != LINESEARCH_CUBICINTERP) ||
182 if (fnew >= fold + (one-c1_)*alpha*sgold) {
183 curvcond = true;
184 }
185 }
186 else if (econd_ == CURVATURECONDITION_NULL) {
187 curvcond = true;
188 }
189 else {
190 updateIterate(*xtst_,x,s,alpha,con);
191 obj.update(*xtst_);
192 obj.gradient(*g_,*xtst_,tol);
193 Real sgnew(0);
194 if ( con.isActivated() ) {
195 d_->set(s);
196 d_->scale(-alpha);
197 con.pruneActive(*d_,s,x);
198 sgnew = -d_->dot(g_->dual());
199 }
200 else {
201 sgnew = s.dot(g_->dual());
202 }
203 ls_ngrad++;
204
206 && (sgnew >= c2_*sgold))
208 && (std::abs(sgnew) <= c2_*std::abs(sgold)))
210 && (c2_*sgold <= sgnew && sgnew <= -c3_*sgold))
212 && (c2_*sgold <= sgnew && sgnew <= (two*c1_ - one)*sgold)) ) {
213 curvcond = true;
214 }
215 }
216 }
217
218 if(fnew<fmin_) {
219 fmin_ = fnew;
220 alphaMin_ = alpha;
221 }
222
223 if (type == LINESEARCH_BACKTRACKING || type == LINESEARCH_CUBICINTERP) {
225 return ((armijo && curvcond) || itcond_);
226 }
227 else {
228 return (armijo || itcond_);
229 }
230 }
231 else {
232 return ((armijo && curvcond) || itcond_);
233 }
234 }
235
236 virtual Real getInitialAlpha(int &ls_neval, int &ls_ngrad, const Real fval, const Real gs,
237 const Vector<Real> &x, const Vector<Real> &s,
239 Real val(1), one(1), half(0.5);
240 if (useralpha_ || usePrevAlpha_ ) {
241 val = alpha0_;
242 }
243 else {
245 Real tol = std::sqrt(ROL_EPSILON<Real>());
246 // Evaluate objective at x + s
247 updateIterate(*d_,x,s,one,con);
248 obj.update(*d_);
249 Real fnew = obj.value(*d_,tol);
250 ls_neval++;
251 // Minimize quadratic interpolate to compute new alpha
252 Real denom = (fnew - fval - gs);
253 Real alpha = ((denom > ROL_EPSILON<Real>()) ? -half*gs/denom : one);
254 val = ((alpha > alpha0bnd_) ? alpha : one);
255 }
256 else {
257 val = one;
258 }
259 }
260 return val;
261 }
262
263 void setNextInitialAlpha( Real alpha ) {
264 if( usePrevAlpha_ ) {
265 alpha0_ = alpha;
266 }
267 }
268
269 void updateIterate(Vector<Real> &xnew, const Vector<Real> &x, const Vector<Real> &s, Real alpha,
270 BoundConstraint<Real> &con ) {
271
272 xnew.set(x);
273 xnew.axpy(alpha,s);
274
275 if ( con.isActivated() ) {
276 con.project(xnew);
277 }
278
279 }
280
282 return itcond_ && acceptMin_;
283 }
284
285 bool takeNoStep() {
286 return itcond_ && !acceptMin_;
287 }
288};
289
290}
291
293
294#endif
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
Contains definitions of custom data types in ROL.
Provides the interface to apply upper and lower bound constraints.
void pruneInactive(Vector< Real > &v, const Vector< Real > &x, Real eps=Real(0))
Set variables to zero if they correspond to the -inactive set.
void pruneActive(Vector< Real > &v, const Vector< Real > &x, Real eps=Real(0))
Set variables to zero if they correspond to the -active set.
bool isActivated(void) const
Check if bounds are on.
virtual void project(Vector< Real > &x)
Project optimization variables onto the bounds.
Provides interface for and implements line searches.
virtual bool status(const ELineSearch type, int &ls_neval, int &ls_ngrad, const Real alpha, const Real fold, const Real sgold, const Real fnew, const Vector< Real > &x, const Vector< Real > &s, Objective< Real > &obj, BoundConstraint< Real > &con)
ECurvatureCondition econd_
void setData(Real &eps, const Vector< Real > &g)
ROL::Ptr< Vector< Real > > g_
void updateIterate(Vector< Real > &xnew, const Vector< Real > &x, const Vector< Real > &s, Real alpha, BoundConstraint< Real > &con)
virtual void initialize(const Vector< Real > &x, const Vector< Real > &s, const Vector< Real > &g, Objective< Real > &obj, BoundConstraint< Real > &con)
LineSearch(ROL::ParameterList &parlist)
ROL::Ptr< Vector< Real > > d_
virtual Real getInitialAlpha(int &ls_neval, int &ls_ngrad, const Real fval, const Real gs, const Vector< Real > &x, const Vector< Real > &s, Objective< Real > &obj, BoundConstraint< Real > &con)
void setMaxitUpdate(Real &alpha, Real &fnew, const Real &fold)
void setNextInitialAlpha(Real alpha)
virtual void run(Real &alpha, Real &fval, int &ls_neval, int &ls_ngrad, const Real &gs, const Vector< Real > &s, const Vector< Real > &x, Objective< Real > &obj, BoundConstraint< Real > &con)=0
ROL::Ptr< Vector< Real > > grad_
ROL::Ptr< Vector< Real > > xtst_
Provides the interface to evaluate objective functions.
virtual void gradient(Vector< Real > &g, const Vector< Real > &x, Real &tol)
Compute gradient.
virtual Real value(const Vector< Real > &x, Real &tol)=0
Compute value.
virtual void update(const Vector< Real > &x, UpdateType type, int iter=-1)
Update objective function.
Defines the linear algebra or vector space interface.
virtual void set(const Vector &x)
Set where .
virtual ROL::Ptr< Vector > clone() const =0
Clone to make a new (uninitialized) vector.
virtual void axpy(const Real alpha, const Vector &x)
Compute where .
virtual Real dot(const Vector &x) const =0
Compute where .
EDescent StringToEDescent(std::string s)
@ DESCENT_STEEPEST
@ DESCENT_NONLINEARCG
ECurvatureCondition
@ CURVATURECONDITION_GENERALIZEDWOLFE
@ CURVATURECONDITION_APPROXIMATEWOLFE
@ CURVATURECONDITION_WOLFE
@ CURVATURECONDITION_NULL
@ CURVATURECONDITION_STRONGWOLFE
@ CURVATURECONDITION_GOLDSTEIN
ELineSearch
@ LINESEARCH_BACKTRACKING
@ LINESEARCH_CUBICINTERP
ECurvatureCondition StringToECurvatureCondition(std::string s)