ROL
ROL_NewtonKrylovStep.hpp
Go to the documentation of this file.
1// @HEADER
2// ************************************************************************
3//
4// Rapid Optimization Library (ROL) Package
5// Copyright (2014) Sandia Corporation
6//
7// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8// license for use of this work by or on behalf of the U.S. Government.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// 3. Neither the name of the Corporation nor the names of the
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// Questions? Contact lead developers:
38// Drew Kouri (dpkouri@sandia.gov) and
39// Denis Ridzal (dridzal@sandia.gov)
40//
41// ************************************************************************
42// @HEADER
43
44#ifndef ROL_NEWTONKRYLOVSTEP_H
45#define ROL_NEWTONKRYLOVSTEP_H
46
47#include "ROL_Types.hpp"
48#include "ROL_Step.hpp"
49
50#include "ROL_Secant.hpp"
51#include "ROL_KrylovFactory.hpp"
53
54#include <sstream>
55#include <iomanip>
56
62
63namespace ROL {
64
65template <class Real>
66class NewtonKrylovStep : public Step<Real> {
67private:
68
69 ROL::Ptr<Secant<Real> > secant_;
70 ROL::Ptr<Krylov<Real> > krylov_;
71
74
75 ROL::Ptr<Vector<Real> > gp_;
76
80 const bool computeObj_;
81
83
84 std::string krylovName_;
85 std::string secantName_;
86
87
88 class HessianNK : public LinearOperator<Real> {
89 private:
90 const ROL::Ptr<Objective<Real> > obj_;
91 const ROL::Ptr<Vector<Real> > x_;
92 public:
93 HessianNK(const ROL::Ptr<Objective<Real> > &obj,
94 const ROL::Ptr<Vector<Real> > &x) : obj_(obj), x_(x) {}
95 void apply(Vector<Real> &Hv, const Vector<Real> &v, Real &tol) const {
96 obj_->hessVec(Hv,v,*x_,tol);
97 }
98 };
99
100 class PrecondNK : public LinearOperator<Real> {
101 private:
102 const ROL::Ptr<Objective<Real> > obj_;
103 const ROL::Ptr<Vector<Real> > x_;
104 public:
105 PrecondNK(const ROL::Ptr<Objective<Real> > &obj,
106 const ROL::Ptr<Vector<Real> > &x) : obj_(obj), x_(x) {}
107 void apply(Vector<Real> &Hv, const Vector<Real> &v, Real &tol) const {
108 Hv.set(v.dual());
109 }
110 void applyInverse(Vector<Real> &Hv, const Vector<Real> &v, Real &tol) const {
111 obj_->precond(Hv,v,*x_,tol);
112 }
113 };
114
115public:
116
117 using Step<Real>::initialize;
118 using Step<Real>::compute;
119 using Step<Real>::update;
120
128 NewtonKrylovStep( ROL::ParameterList &parlist, const bool computeObj = true )
129 : Step<Real>(), secant_(ROL::nullPtr), krylov_(ROL::nullPtr),
130 gp_(ROL::nullPtr), iterKrylov_(0), flagKrylov_(0),
131 verbosity_(0), computeObj_(computeObj), useSecantPrecond_(false) {
132 // Parse ParameterList
133 ROL::ParameterList& Glist = parlist.sublist("General");
134 useSecantPrecond_ = Glist.sublist("Secant").get("Use as Preconditioner", false);
135 verbosity_ = Glist.get("Print Verbosity",0);
136 // Initialize Krylov object
137 krylovName_ = Glist.sublist("Krylov").get("Type","Conjugate Gradients");
139 krylov_ = KrylovFactory<Real>(parlist);
140 // Initialize secant object
141 secantName_ = Glist.sublist("Secant").get("Type","Limited-Memory BFGS");
143 if ( useSecantPrecond_ ) {
144 secant_ = SecantFactory<Real>(parlist);
145 }
146 }
147
158 NewtonKrylovStep(ROL::ParameterList &parlist,
159 const ROL::Ptr<Krylov<Real> > &krylov,
160 const ROL::Ptr<Secant<Real> > &secant,
161 const bool computeObj = true)
162 : Step<Real>(), secant_(secant), krylov_(krylov),
164 gp_(ROL::nullPtr), iterKrylov_(0), flagKrylov_(0),
165 verbosity_(0), computeObj_(computeObj), useSecantPrecond_(false) {
166 // Parse ParameterList
167 ROL::ParameterList& Glist = parlist.sublist("General");
168 useSecantPrecond_ = Glist.sublist("Secant").get("Use as Preconditioner", false);
169 verbosity_ = Glist.get("Print Verbosity",0);
170 // Initialize secant object
171 if ( useSecantPrecond_ ) {
172 if(secant_ == ROL::nullPtr ) {
173 secantName_ = Glist.sublist("Secant").get("Type","Limited-Memory BFGS");
175 secant_ = SecantFactory<Real>(parlist);
176 }
177 else {
178 secantName_ = Glist.sublist("Secant").get("User Defined Secant Name",
179 "Unspecified User Defined Secant Method");
180 }
181 }
182 // Initialize Krylov object
183 if ( krylov_ == ROL::nullPtr ) {
184 krylovName_ = Glist.sublist("Krylov").get("Type","Conjugate Gradients");
186 krylov_ = KrylovFactory<Real>(parlist);
187 }
188 else {
189 krylovName_ = Glist.sublist("Krylov").get("User Defined Krylov Name",
190 "Unspecified User Defined Krylov Method");
191 }
192 }
193
194 void initialize( Vector<Real> &x, const Vector<Real> &s, const Vector<Real> &g,
196 AlgorithmState<Real> &algo_state ) {
197 Step<Real>::initialize(x,s,g,obj,bnd,algo_state);
198 if ( useSecantPrecond_ ) {
199 gp_ = g.clone();
200 }
201 }
202
205 AlgorithmState<Real> &algo_state ) {
206 Real one(1);
207 ROL::Ptr<StepState<Real> > step_state = Step<Real>::getState();
208
209 // Build Hessian and Preconditioner object
210 ROL::Ptr<Objective<Real> > obj_ptr = ROL::makePtrFromRef(obj);
211 ROL::Ptr<LinearOperator<Real> > hessian
212 = ROL::makePtr<HessianNK>(obj_ptr,algo_state.iterateVec);
213 ROL::Ptr<LinearOperator<Real> > precond;
214 if ( useSecantPrecond_ ) {
215 precond = secant_;
216 }
217 else {
218 precond = ROL::makePtr<PrecondNK>(obj_ptr,algo_state.iterateVec);
219 }
220
221 // Run Krylov method
222 flagKrylov_ = 0;
223 krylov_->run(s,*hessian,*(step_state->gradientVec),*precond,iterKrylov_,flagKrylov_);
224
225 // Check Krylov flags
226 if ( flagKrylov_ == 2 && iterKrylov_ <= 1 ) {
227 s.set((step_state->gradientVec)->dual());
228 }
229 s.scale(-one);
230 }
231
232 void update( Vector<Real> &x, const Vector<Real> &s,
234 AlgorithmState<Real> &algo_state ) {
235 Real tol = std::sqrt(ROL_EPSILON<Real>());
236 ROL::Ptr<StepState<Real> > step_state = Step<Real>::getState();
237 step_state->SPiter = iterKrylov_;
238 step_state->SPflag = flagKrylov_;
239
240 // Update iterate
241 algo_state.iter++;
242 x.plus(s);
243 (step_state->descentVec)->set(s);
244 algo_state.snorm = s.norm();
245
246 // Compute new gradient
247 if ( useSecantPrecond_ ) {
248 gp_->set(*(step_state->gradientVec));
249 }
250 obj.update(x,true,algo_state.iter);
251 if ( computeObj_ ) {
252 algo_state.value = obj.value(x,tol);
253 algo_state.nfval++;
254 }
255 obj.gradient(*(step_state->gradientVec),x,tol);
256 algo_state.ngrad++;
257
258 // Update Secant Information
259 if ( useSecantPrecond_ ) {
260 secant_->updateStorage(x,*(step_state->gradientVec),*gp_,s,algo_state.snorm,algo_state.iter+1);
261 }
262
263 // Update algorithm state
264 (algo_state.iterateVec)->set(x);
265 algo_state.gnorm = step_state->gradientVec->norm();
266 }
267
268 std::string printHeader( void ) const {
269 std::stringstream hist;
270
271 if( verbosity_>0 ) {
272 hist << std::string(109,'-') << "\n";
274 hist << " status output definitions\n\n";
275 hist << " iter - Number of iterates (steps taken) \n";
276 hist << " value - Objective function value \n";
277 hist << " gnorm - Norm of the gradient\n";
278 hist << " snorm - Norm of the step (update to optimization vector)\n";
279 hist << " #fval - Cumulative number of times the objective function was evaluated\n";
280 hist << " #grad - Number of times the gradient was computed\n";
281 hist << " iterCG - Number of Krylov iterations used to compute search direction\n";
282 hist << " flagCG - Krylov solver flag" << "\n";
283 hist << std::string(109,'-') << "\n";
284 }
285
286 hist << " ";
287 hist << std::setw(6) << std::left << "iter";
288 hist << std::setw(15) << std::left << "value";
289 hist << std::setw(15) << std::left << "gnorm";
290 hist << std::setw(15) << std::left << "snorm";
291 hist << std::setw(10) << std::left << "#fval";
292 hist << std::setw(10) << std::left << "#grad";
293 hist << std::setw(10) << std::left << "iterCG";
294 hist << std::setw(10) << std::left << "flagCG";
295 hist << "\n";
296 return hist.str();
297 }
298 std::string printName( void ) const {
299 std::stringstream hist;
300 hist << "\n" << EDescentToString(DESCENT_NEWTONKRYLOV);
301 hist << " using " << krylovName_;
302 if ( useSecantPrecond_ ) {
303 hist << " with " << ESecantToString(esec_) << " preconditioning";
304 }
305 hist << "\n";
306 return hist.str();
307 }
308 std::string print( AlgorithmState<Real> &algo_state, bool print_header = false ) const {
309 std::stringstream hist;
310 hist << std::scientific << std::setprecision(6);
311 if ( algo_state.iter == 0 ) {
312 hist << printName();
313 }
314 if ( print_header ) {
315 hist << printHeader();
316 }
317 if ( algo_state.iter == 0 ) {
318 hist << " ";
319 hist << std::setw(6) << std::left << algo_state.iter;
320 hist << std::setw(15) << std::left << algo_state.value;
321 hist << std::setw(15) << std::left << algo_state.gnorm;
322 hist << "\n";
323 }
324 else {
325 hist << " ";
326 hist << std::setw(6) << std::left << algo_state.iter;
327 hist << std::setw(15) << std::left << algo_state.value;
328 hist << std::setw(15) << std::left << algo_state.gnorm;
329 hist << std::setw(15) << std::left << algo_state.snorm;
330 hist << std::setw(10) << std::left << algo_state.nfval;
331 hist << std::setw(10) << std::left << algo_state.ngrad;
332 hist << std::setw(10) << std::left << iterKrylov_;
333 hist << std::setw(10) << std::left << flagKrylov_;
334 hist << "\n";
335 }
336 return hist.str();
337 }
338}; // class NewtonKrylovStep
339
340} // namespace ROL
341
342#endif
virtual void update(const Vector< Real > &u_old, const Vector< Real > &u_new, const Vector< Real > &z, bool flag=true, int iter=-1)
virtual void initialize(const Vector< Real > &x)
Initialize temporary variables.
Contains definitions of custom data types in ROL.
Provides the interface to apply upper and lower bound constraints.
Provides definitions for Krylov solvers.
Provides the interface to apply a linear operator.
const ROL::Ptr< Objective< Real > > obj_
HessianNK(const ROL::Ptr< Objective< Real > > &obj, const ROL::Ptr< Vector< Real > > &x)
const ROL::Ptr< Vector< Real > > x_
void apply(Vector< Real > &Hv, const Vector< Real > &v, Real &tol) const
void applyInverse(Vector< Real > &Hv, const Vector< Real > &v, Real &tol) const
const ROL::Ptr< Vector< Real > > x_
void apply(Vector< Real > &Hv, const Vector< Real > &v, Real &tol) const
const ROL::Ptr< Objective< Real > > obj_
PrecondNK(const ROL::Ptr< Objective< Real > > &obj, const ROL::Ptr< Vector< Real > > &x)
ROL::Ptr< Vector< Real > > gp_
std::string print(AlgorithmState< Real > &algo_state, bool print_header=false) const
ROL::Ptr< Secant< Real > > secant_
Secant object (used for quasi-Newton).
int flagKrylov_
Termination flag for Krylov method (used for inexact Newton).
int verbosity_
Verbosity level.
void compute(Vector< Real > &s, const Vector< Real > &x, Objective< Real > &obj, BoundConstraint< Real > &bnd, AlgorithmState< Real > &algo_state)
bool useSecantPrecond_
Whether or not a secant approximation is used for preconditioning inexact Newton.
void initialize(Vector< Real > &x, const Vector< Real > &s, const Vector< Real > &g, Objective< Real > &obj, BoundConstraint< Real > &bnd, AlgorithmState< Real > &algo_state)
int iterKrylov_
Number of Krylov iterations (used for inexact Newton).
std::string printName(void) const
Print step name.
NewtonKrylovStep(ROL::ParameterList &parlist, const bool computeObj=true)
Constructor.
void update(Vector< Real > &x, const Vector< Real > &s, Objective< Real > &obj, BoundConstraint< Real > &bnd, AlgorithmState< Real > &algo_state)
std::string printHeader(void) const
Print iterate header.
NewtonKrylovStep(ROL::ParameterList &parlist, const ROL::Ptr< Krylov< Real > > &krylov, const ROL::Ptr< Secant< Real > > &secant, const bool computeObj=true)
Constructor.
ROL::Ptr< Krylov< Real > > krylov_
Krylov solver object (used for inexact Newton).
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.
Provides interface for and implements limited-memory secant operators.
Provides the interface to compute optimization steps.
Definition ROL_Step.hpp:68
virtual void initialize(Vector< Real > &x, const Vector< Real > &g, Objective< Real > &obj, BoundConstraint< Real > &con, AlgorithmState< Real > &algo_state)
Initialize step with bound constraint.
Definition ROL_Step.hpp:88
ROL::Ptr< StepState< Real > > getState(void)
Definition ROL_Step.hpp:73
Defines the linear algebra or vector space interface.
virtual Real norm() const =0
Returns where .
virtual void set(const Vector &x)
Set where .
virtual void scale(const Real alpha)=0
Compute where .
virtual const Vector & dual() const
Return dual representation of , for example, the result of applying a Riesz map, or change of basis,...
virtual void plus(const Vector &x)=0
Compute , where .
virtual ROL::Ptr< Vector > clone() const =0
Clone to make a new (uninitialized) vector.
EKrylov StringToEKrylov(std::string s)
Real ROL_EPSILON(void)
Platform-dependent machine epsilon.
Definition ROL_Types.hpp:91
@ DESCENT_NEWTONKRYLOV
ESecant StringToESecant(std::string s)
Ptr< Krylov< Real > > KrylovFactory(ParameterList &parlist)
@ SECANT_USERDEFINED
std::string EDescentToString(EDescent tr)
ROL::Ptr< Secant< Real > > SecantFactory(ROL::ParameterList &parlist, ESecantMode mode=SECANTMODE_BOTH)
std::string ESecantToString(ESecant tr)
State for algorithm class. Will be used for restarts.
ROL::Ptr< Vector< Real > > iterateVec