ROL
ROL_LineSearch_U.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_U_H
11 #define ROL_LINESEARCH_U_H
12 
17 #include "ROL_Ptr.hpp"
18 #include "ROL_ParameterList.hpp"
19 #include "ROL_Types.hpp"
20 #include "ROL_Objective.hpp"
21 #include "ROL_ScalarFunction.hpp"
23 
24 namespace ROL {
25 
26 template<typename Real>
27 class LineSearch_U {
28 private:
29 
32 
33  bool useralpha_;
34  bool usePrevAlpha_; // Use the previous step's accepted alpha as an initial guess
35  Real alpha0_;
36  Real alpha0bnd_; // Lower bound for initial alpha...if below, set initial alpha to one
37  int maxit_;
38  Real c1_;
39  Real c2_;
40  Real c3_;
41  Real eps_;
42  Real fmin_; // smallest fval encountered
43  Real alphaMin_; // Alpha that yields the smallest fval encountered
44  bool acceptMin_; // Use smallest fval if sufficient decrease not satisfied
45  bool itcond_; // true if maximum function evaluations reached
47 
48  Ptr<Vector<Real>> xtst_;
49 
50  Real dirDeriv(const Vector<Real> &x, // current iterate
51  const Vector<Real> &s, // current trial step
52  const Real alpha, // current step length
53  const Real fnew, // f(x+alpha*s)
54  Objective<Real> &obj) {
55  Real tol = std::sqrt(ROL_EPSILON<Real>());
56  Real val(0);
57  xtst_->set(x); xtst_->axpy(alpha,s);
58  if (FDdirDeriv_) {
59  Real snorm = s.norm();
60  if (snorm > static_cast<Real>(0)) {
61  Real xnorm = xtst_->norm();
62  Real cbrteps = std::cbrt(ROL_EPSILON<Real>());
63  Real h = cbrteps*std::max(xnorm/snorm,static_cast<Real>(1));
64  xtst_->axpy(h,s);
66  Real ftrial = obj.value(*xtst_,tol);
67  val = (ftrial - fnew) / h;
68  }
69  }
70  else {
71  val = obj.dirDeriv(*xtst_,s,tol);
72  }
73  return val;
74  }
75 
76 public:
77 
78  virtual ~LineSearch_U() {}
79 
80  // Constructor
81  LineSearch_U( ParameterList &parlist ) {
82  Real one(1), p9(0.9), p6(0.6), p4(0.4), oem4(1.e-4), zero(0);
83  // Enumerations
84  std::string descentType = parlist.sublist("Step").sublist("Line Search").sublist("Descent Method").get("Type","Quasi-Newton Method");
85  edesc_ = StringToEDescentU(descentType);
86  std::string condType = parlist.sublist("Step").sublist("Line Search").sublist("Curvature Condition").get("Type","Strong Wolfe Conditions");
88  // Linesearch Parameters
89  alpha0_ = parlist.sublist("Step").sublist("Line Search").get("Initial Step Size",one);
90  alpha0bnd_ = parlist.sublist("Step").sublist("Line Search").get("Lower Bound for Initial Step Size",one);
91  useralpha_ = parlist.sublist("Step").sublist("Line Search").get("User Defined Initial Step Size",false);
92  usePrevAlpha_ = parlist.sublist("Step").sublist("Line Search").get("Use Previous Step Length as Initial Guess",false);
93  acceptMin_ = parlist.sublist("Step").sublist("Line Search").get("Accept Linesearch Minimizer",false);
94  maxit_ = parlist.sublist("Step").sublist("Line Search").get("Function Evaluation Limit",20);
95  c1_ = parlist.sublist("Step").sublist("Line Search").get("Sufficient Decrease Tolerance",oem4);
96  c2_ = parlist.sublist("Step").sublist("Line Search").sublist("Curvature Condition").get("General Parameter",p9);
97  c3_ = parlist.sublist("Step").sublist("Line Search").sublist("Curvature Condition").get("Generalized Wolfe Parameter",p6);
98 
99  fmin_ = std::numeric_limits<Real>::max();
100  alphaMin_ = 0;
101  itcond_ = false;
102  FDdirDeriv_ = parlist.sublist("Step").sublist("Line Search").get("Finite Difference Directional Derivative",false);
103 
104  c1_ = ((c1_ < zero) ? oem4 : c1_);
105  c2_ = ((c2_ < zero) ? p9 : c2_);
106  c3_ = ((c3_ < zero) ? p9 : c3_);
107  if ( c2_ <= c1_ ) {
108  c1_ = oem4;
109  c2_ = p9;
110  }
111  if ( edesc_ == DESCENT_U_NONLINEARCG ) {
112  c2_ = p4;
113  c3_ = std::min(one-c2_,c3_);
114  }
115  }
116 
117  virtual void initialize(const Vector<Real> &x, const Vector<Real> &g) {
118  xtst_ = x.clone();
119  }
120 
121  virtual void run( Real &alpha, Real &fval, int &ls_neval, int &ls_ngrad,
122  const Real &gs, const Vector<Real> &s, const Vector<Real> &x,
123  Objective<Real> &obj ) = 0;
124 
125  // use this function to modify alpha and fval if the maximum number of iterations
126  // are reached
127  void setMaxitUpdate(Real &alpha, Real &fnew, const Real &fold) {
128  // Use local minimizer
129  if( itcond_ && acceptMin_ ) {
130  alpha = alphaMin_;
131  fnew = fmin_;
132  }
133  // Take no step
134  else if(itcond_ && !acceptMin_) {
135  alpha = 0;
136  fnew = fold;
137  }
138  setNextInitialAlpha(alpha);
139  }
140 
141 protected:
142  virtual bool status( const ELineSearchU type, int &ls_neval, int &ls_ngrad, const Real alpha,
143  const Real fold, const Real sgold, const Real fnew,
144  const Vector<Real> &x, const Vector<Real> &s,
145  Objective<Real> &obj ) {
146  const Real one(1), two(2);
147 
148  // Check Armijo Condition
149  bool armijo = false;
150  if ( fnew <= fold + c1_*alpha*sgold ) {
151  armijo = true;
152  }
153 
154  // Check Maximum Iteration
155  itcond_ = false;
156  if ( ls_neval >= maxit_ ) {
157  itcond_ = true;
158  }
159 
160  // Check Curvature Condition
161  bool curvcond = false;
162  if ( armijo && ((type != LINESEARCH_U_BACKTRACKING && type != LINESEARCH_U_CUBICINTERP) ||
163  (edesc_ == DESCENT_U_NONLINEARCG)) ) {
165  if (fnew >= fold + (one-c1_)*alpha*sgold) {
166  curvcond = true;
167  }
168  }
169  else if (econd_ == CURVATURECONDITION_U_NULL) {
170  curvcond = true;
171  }
172  else {
173  Real sgnew = dirDeriv(x,s,alpha,fnew,obj); //ls_ngrad++;
175  && (sgnew >= c2_*sgold))
177  && (std::abs(sgnew) <= c2_*std::abs(sgold)))
179  && (c2_*sgold <= sgnew && sgnew <= -c3_*sgold))
181  && (c2_*sgold <= sgnew && sgnew <= (two*c1_ - one)*sgold)) ) {
182  curvcond = true;
183  }
184  }
185  }
186 
187  if(fnew<fmin_) {
188  fmin_ = fnew;
189  alphaMin_ = alpha;
190  }
191 
192  if (type == LINESEARCH_U_BACKTRACKING || type == LINESEARCH_U_CUBICINTERP) {
193  if (edesc_ == DESCENT_U_NONLINEARCG) {
194  return ((armijo && curvcond) || itcond_);
195  }
196  else {
197  return (armijo || itcond_);
198  }
199  }
200  else {
201  return ((armijo && curvcond) || itcond_);
202  }
203  }
204 
205  virtual Real getInitialAlpha(int &ls_neval, int &ls_ngrad, const Real fval, const Real gs,
206  const Vector<Real> &x, const Vector<Real> &s,
207  Objective<Real> &obj) {
208  Real val(1);
209  if (useralpha_ || usePrevAlpha_ ) {
210  val = alpha0_;
211  }
212  else {
213  const Real one(1), half(0.5);
215  Real tol = std::sqrt(ROL_EPSILON<Real>());
216  // Evaluate objective at x + s
217  xtst_->set(x); xtst_->plus(s);
219  Real fnew = obj.value(*xtst_,tol);
220  ls_neval++;
221  // Minimize quadratic interpolate to compute new alpha
222  Real denom = (fnew - fval - gs);
223  Real alpha = ((denom > ROL_EPSILON<Real>()) ? -half*gs/denom : one);
224  val = ((alpha > alpha0bnd_) ? alpha : one);
225  }
226  else {
227  val = one;
228  }
229  }
230  return val;
231  }
232 
233  void setNextInitialAlpha( Real alpha ) {
234  if( usePrevAlpha_ ) {
235  alpha0_ = alpha;
236  }
237  }
238 
240  return itcond_ && acceptMin_;
241  }
242 
243  bool takeNoStep() {
244  return itcond_ && !acceptMin_;
245  }
246 }; // class ROL::LineSearch_U
247 
248 } // namespace ROL
249 
250 #endif
Provides interface for and implements line searches.
virtual void initialize(const Vector< Real > &x, const Vector< Real > &g)
ECurvatureConditionU econd_
Provides the interface to evaluate objective functions.
void setNextInitialAlpha(Real alpha)
virtual ROL::Ptr< Vector > clone() const =0
Clone to make a new (uninitialized) vector.
Real dirDeriv(const Vector< Real > &x, const Vector< Real > &s, const Real alpha, const Real fnew, Objective< Real > &obj)
EDescentU
Enumeration of descent direction types.
Ptr< Vector< Real > > xtst_
virtual bool status(const ELineSearchU 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)
virtual Real value(const Vector< Real > &x, Real &tol)=0
Compute value.
virtual Real dirDeriv(const Vector< Real > &x, const Vector< Real > &d, Real &tol)
Compute directional derivative.
Contains definitions of custom data types in ROL.
void setMaxitUpdate(Real &alpha, Real &fnew, const Real &fold)
ELineSearchU
Enumeration of line-search types.
ECurvatureConditionU
Enumeration of line-search curvature conditions.
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:46
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)
virtual void update(const Vector< Real > &x, UpdateType type, int iter=-1)
Update objective function.
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
EDescentU StringToEDescentU(std::string s)
LineSearch_U(ParameterList &parlist)
virtual Real norm() const =0
Returns where .
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)=0
ECurvatureConditionU StringToECurvatureConditionU(std::string s)