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"
22 #include "ROL_BoundConstraint.hpp"
23 #include "ROL_ScalarFunction.hpp"
24 
25 namespace ROL {
26 
27 template<class Real>
28 class LineSearch {
29 private:
30 
33 
34  bool useralpha_;
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 
54 public:
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 
132 protected:
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,
136  Objective<Real> &obj, BoundConstraint<Real> &con ) {
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) ||
180  (edesc_ == DESCENT_NONLINEARCG)) ) {
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 
205  if ( ((econd_ == CURVATURECONDITION_WOLFE)
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) {
224  if (edesc_ == DESCENT_NONLINEARCG) {
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 
292 #include "ROL_LineSearchFactory.hpp"
293 
294 #endif
Provides the interface to evaluate objective functions.
void setData(Real &eps, const Vector< Real > &g)
void updateIterate(Vector< Real > &xnew, const Vector< Real > &x, const Vector< Real > &s, Real alpha, BoundConstraint< Real > &con)
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)
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 .
Definition: ROL_Vector.hpp:119
bool isActivated(void) const
Check if bounds are on.
virtual Real value(const Vector< Real > &x, Real &tol)=0
Compute value.
Contains definitions of custom data types in ROL.
ELineSearch
Enumeration of line-search types.
Definition: ROL_Types.hpp:628
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:46
virtual void update(const Vector< Real > &x, UpdateType type, int iter=-1)
Update objective function.
virtual Real dot(const Vector &x) const =0
Compute where .
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
ROL::Ptr< Vector< Real > > g_
EDescent StringToEDescent(std::string s)
Definition: ROL_Types.hpp:438
virtual void gradient(Vector< Real > &g, const Vector< Real > &x, Real &tol)
Compute gradient.
Provides interface for and implements line searches.
void setMaxitUpdate(Real &alpha, Real &fnew, const Real &fold)
ROL::Ptr< Vector< Real > > grad_
virtual void project(Vector< Real > &x)
Project optimization variables onto the bounds.
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.
Provides the interface to apply upper and lower bound constraints.
virtual ~LineSearch()
ECurvatureCondition
Enumeration of line-search curvature conditions.
Definition: ROL_Types.hpp:711
LineSearch(ROL::ParameterList &parlist)
virtual void set(const Vector &x)
Set where .
Definition: ROL_Vector.hpp:175
ECurvatureCondition StringToECurvatureCondition(std::string s)
Definition: ROL_Types.hpp:771
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
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)
ROL::Ptr< Vector< Real > > xtst_
ECurvatureCondition econd_
EDescent
Enumeration of descent direction types.
Definition: ROL_Types.hpp:381
ROL::Ptr< Vector< Real > > d_
virtual void initialize(const Vector< Real > &x, const Vector< Real > &s, const Vector< Real > &g, Objective< Real > &obj, BoundConstraint< Real > &con)
void setNextInitialAlpha(Real alpha)