ROL
ROL_TypeB_LinMoreAlgorithm_Def.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_TYPEB_LINMOREALGORITHM_DEF_HPP
11#define ROL_TYPEB_LINMOREALGORITHM_DEF_HPP
12
13namespace ROL {
14namespace TypeB {
15
16template<typename Real>
18 const Ptr<Secant<Real>> &secant) {
19 // Set status test
20 status_->reset();
21 status_->add(makePtr<StatusTest<Real>>(list));
22
23 ParameterList &trlist = list.sublist("Step").sublist("Trust Region");
24 // Trust-Region Parameters
25 state_->searchSize = trlist.get("Initial Radius", -1.0);
26 delMax_ = trlist.get("Maximum Radius", ROL_INF<Real>());
27 eta0_ = trlist.get("Step Acceptance Threshold", 0.05);
28 eta1_ = trlist.get("Radius Shrinking Threshold", 0.05);
29 eta2_ = trlist.get("Radius Growing Threshold", 0.9);
30 gamma0_ = trlist.get("Radius Shrinking Rate (Negative rho)", 0.0625);
31 gamma1_ = trlist.get("Radius Shrinking Rate (Positive rho)", 0.25);
32 gamma2_ = trlist.get("Radius Growing Rate", 2.5);
33 TRsafe_ = trlist.get("Safeguard Size", 100.0);
35 interpRad_ = trlist.get("Use Radius Interpolation", false);
36 // Nonmonotone Parameters
37 storageNM_ = trlist.get("Nonmonotone Storage Size", 0);
38 useNM_ = (storageNM_ <= 0 ? false : true);
39 // Krylov Parameters
40 maxit_ = list.sublist("General").sublist("Krylov").get("Iteration Limit", 20);
41 tol1_ = list.sublist("General").sublist("Krylov").get("Absolute Tolerance", 1e-4);
42 tol2_ = list.sublist("General").sublist("Krylov").get("Relative Tolerance", 1e-2);
43 // Algorithm-Specific Parameters
44 ROL::ParameterList &lmlist = trlist.sublist("Lin-More");
45 minit_ = lmlist.get("Maximum Number of Minor Iterations", 10);
46 mu0_ = lmlist.get("Sufficient Decrease Parameter", 1e-2);
47 spexp_ = lmlist.get("Relative Tolerance Exponent", 1.0);
48 spexp_ = std::max(static_cast<Real>(1),std::min(spexp_,static_cast<Real>(2)));
49 redlim_ = lmlist.sublist("Cauchy Point").get("Maximum Number of Reduction Steps", 10);
50 explim_ = lmlist.sublist("Cauchy Point").get("Maximum Number of Expansion Steps", 10);
51 alpha_ = lmlist.sublist("Cauchy Point").get("Initial Step Size", 1.0);
52 normAlpha_ = lmlist.sublist("Cauchy Point").get("Normalize Initial Step Size", false);
53 interpf_ = lmlist.sublist("Cauchy Point").get("Reduction Rate", 0.1);
54 extrapf_ = lmlist.sublist("Cauchy Point").get("Expansion Rate", 10.0);
55 qtol_ = lmlist.sublist("Cauchy Point").get("Decrease Tolerance", 1e-8);
56 interpfPS_ = lmlist.sublist("Projected Search").get("Backtracking Rate", 0.5);
57 pslim_ = lmlist.sublist("Projected Search").get("Maximum Number of Steps", 20);
58 // Inexactness Information
59 ParameterList &glist = list.sublist("General");
60 useInexact_.clear();
61 useInexact_.push_back(glist.get("Inexact Objective Function", false));
62 useInexact_.push_back(glist.get("Inexact Gradient", false));
63 useInexact_.push_back(glist.get("Inexact Hessian-Times-A-Vector", false));
64 // Trust-Region Inexactness Parameters
65 ParameterList &ilist = trlist.sublist("Inexact").sublist("Gradient");
66 scale0_ = ilist.get("Tolerance Scaling", static_cast<Real>(0.1));
67 scale1_ = ilist.get("Relative Tolerance", static_cast<Real>(2));
68 // Inexact Function Evaluation Information
69 ParameterList &vlist = trlist.sublist("Inexact").sublist("Value");
70 scale_ = vlist.get("Tolerance Scaling", static_cast<Real>(1.e-1));
71 omega_ = vlist.get("Exponent", static_cast<Real>(0.9));
72 force_ = vlist.get("Forcing Sequence Initial Value", static_cast<Real>(1.0));
73 updateIter_ = vlist.get("Forcing Sequence Update Frequency", static_cast<int>(10));
74 forceFactor_ = vlist.get("Forcing Sequence Reduction Factor", static_cast<Real>(0.1));
75 // Output Parameters
76 verbosity_ = list.sublist("General").get("Output Level",0);
78 // Secant Information
79 useSecantPrecond_ = list.sublist("General").sublist("Secant").get("Use as Preconditioner", false);
80 useSecantHessVec_ = list.sublist("General").sublist("Secant").get("Use as Hessian", false);
84 // Initialize trust region model
85 model_ = makePtr<TrustRegionModel_U<Real>>(list,secant,mode);
86 if (secant == nullPtr) {
87 std::string secantType = list.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS");
88 esec_ = StringToESecant(secantType);
89 }
90}
91
92template<typename Real>
94 const Vector<Real> &g,
95 Objective<Real> &obj,
97 std::ostream &outStream) {
98 //const Real one(1);
99 hasEcon_ = true;
100 if (proj_ == nullPtr) {
101 proj_ = makePtr<PolyhedralProjection<Real>>(makePtrFromRef(bnd));
102 hasEcon_ = false;
103 }
104 // Initialize data
106 nhess_ = 0;
107 // Update approximate gradient and approximate objective function.
108 Real ftol = static_cast<Real>(0.1)*ROL_OVERFLOW<Real>();
109 proj_->project(x,outStream); state_->nproj++;
110 state_->iterateVec->set(x);
111 obj.update(x,UpdateType::Initial,state_->iter);
112 state_->value = obj.value(x,ftol);
113 state_->nfval++;
114 //obj.gradient(*state_->gradientVec,x,ftol);
115 computeGradient(x,*state_->gradientVec,*state_->stepVec,state_->searchSize,obj,true,gtol_,state_->gnorm,outStream);
116 state_->ngrad++;
117 //state_->stepVec->set(x);
118 //state_->stepVec->axpy(-one,state_->gradientVec->dual());
119 //proj_->project(*state_->stepVec,outStream); state_->nproj++;
120 //state_->stepVec->axpy(-one,x);
121 //state_->gnorm = state_->stepVec->norm();
122 state_->snorm = ROL_INF<Real>();
123 // Normalize initial CP step length
124 if (normAlpha_) alpha_ /= state_->gradientVec->norm();
125 // Compute initial trust region radius if desired.
126 if ( state_->searchSize <= static_cast<Real>(0) )
127 state_->searchSize = state_->gradientVec->norm();
128 // Initialize null space projection
129 if (hasEcon_) {
130 rcon_ = makePtr<ReducedLinearConstraint<Real>>(proj_->getLinearConstraint(),
131 makePtrFromRef(bnd),
132 makePtrFromRef(x));
133 ns_ = makePtr<NullSpaceOperator<Real>>(rcon_,x,
134 *proj_->getResidual());
135 }
136}
137
138template<typename Real>
140 Real &outTol,
141 Real pRed,
142 Real &fold,
143 int iter,
144 const Vector<Real> &x,
145 const Vector<Real> &xold,
146 Objective<Real> &obj) {
147 outTol = std::sqrt(ROL_EPSILON<Real>());
148 if ( useInexact_[0] ) {
149 if (!(iter%updateIter_) && (iter!=0)) force_ *= forceFactor_;
150 const Real one(1);
151 Real eta = static_cast<Real>(0.999)*std::min(eta1_,one-eta2_);
152 outTol = scale_*std::pow(eta*std::min(pRed,force_),one/omega_);
153 if (inTol > outTol) fold = obj.value(xold,outTol);
154 }
155 // Evaluate objective function at new iterate
157 Real fval = obj.value(x,outTol);
158 return fval;
159}
160
161template<typename Real>
163 Vector<Real> &g,
164 Vector<Real> &pwa,
165 Real del,
166 Objective<Real> &obj,
167 bool accept,
168 Real &gtol,
169 Real &gnorm,
170 std::ostream &outStream) const {
171 if ( useInexact_[1] ) {
172 const Real one(1);
173 Real gtol0 = scale0_*del;
174 if (accept) gtol = gtol0 + one;
175 else gtol0 = scale0_*std::min(gnorm,del);
176 while ( gtol > gtol0 ) {
177 gtol = gtol0;
178 obj.gradient(g,x,gtol);
179 gnorm = TypeB::Algorithm<Real>::optimalityCriterion(x,g,pwa,outStream);
180 gtol0 = scale0_*std::min(gnorm,del);
181 }
182 }
183 else {
184 if (accept) {
185 gtol = std::sqrt(ROL_EPSILON<Real>());
186 obj.gradient(g,x,gtol);
187 gnorm = TypeB::Algorithm<Real>::optimalityCriterion(x,g,pwa,outStream);
188 }
189 }
190}
191
192//template<typename Real>
193//Real LinMoreAlgorithm<Real>::computeValue(Real inTol,
194// Real &outTol,
195// Real pRed,
196// Real &fold,
197// int iter,
198// const Vector<Real> &x,
199// const Vector<Real> &xold,
200// Objective<Real> &obj) {
201// outTol = std::sqrt(ROL_EPSILON<Real>());
202// if ( useInexact_[0] ) {
203// if (!(iter%updateIter_) && (iter!=0)) force_ *= forceFactor_;
204// const Real one(1);
205// Real eta = static_cast<Real>(0.999)*std::min(eta1_,one-eta2_);
206// outTol = scale_*std::pow(eta*std::min(pRed,force_),one/omega_);
207// if (inTol > outTol) fold = obj.value(xold,outTol);
208// }
209// // Evaluate objective function at new iterate
210// obj.update(x,UpdateType::Trial);
211// Real fval = obj.value(x,outTol);
212// return fval;
213//}
214//
215//template<typename Real>
216//void LinMoreAlgorithm<Real>::computeGradient(const Vector<Real> &x,
217// Vector<Real> &g,
218// Vector<Real> &pwa,
219// Real del,
220// Objective<Real> &obj,
221// bool accept,
222// Real &gtol,
223// Real &gnorm,
224// std::ostream &outStream) const {
225// if ( useInexact_[1] ) {
226// const Real one(1);
227// Real gtol0 = scale0_*del;
228// if (accept) gtol = gtol0 + one;
229// else gtol0 = scale0_*std::min(gnorm,del);
230// while ( gtol > gtol0 ) {
231// gtol = gtol0;
232// obj.gradient(g,x,gtol);
233// gnorm = TypeB::Algorithm<Real>::optimalityCriterion(x,g,pwa,outStream);
234// gtol0 = scale0_*std::min(gnorm,del);
235// }
236// }
237// else {
238// if (accept) {
239// gtol = std::sqrt(ROL_EPSILON<Real>());
240// obj.gradient(g,x,gtol);
241// gnorm = TypeB::Algorithm<Real>::optimalityCriterion(x,g,pwa,outStream);
242// }
243// }
244//}
245
246template<typename Real>
248 const Vector<Real> &g,
249 Objective<Real> &obj,
251 std::ostream &outStream ) {
252 const Real zero(0);
253 Real tol0 = std::sqrt(ROL_EPSILON<Real>());
254 Real inTol = static_cast<Real>(0.1)*ROL_OVERFLOW<Real>(), outTol(inTol);
255 Real gfnorm(0), gfnormf(0), tol(0), stol(0), snorm(0);
256 Real ftrial(0), pRed(0), rho(1), q(0), delta(0);
257 int flagCG(0), iterCG(0), maxit(0);
258 // Initialize trust-region data
259 initialize(x,g,obj,bnd,outStream);
260 Ptr<Vector<Real>> s = x.clone();
261 Ptr<Vector<Real>> gmod = g.clone(), gfree = g.clone();
262 Ptr<Vector<Real>> pwa1 = x.clone(), pwa2 = x.clone(), pwa3 = x.clone();
263 Ptr<Vector<Real>> dwa1 = g.clone(), dwa2 = g.clone(), dwa3 = g.clone();
264 // Initialize nonmonotone data
265 Real rhoNM(0), sigmac(0), sigmar(0);
266 Real fr(state_->value), fc(state_->value), fmin(state_->value);
267 TRUtils::ETRFlag TRflagNM;
268 int L(0);
269
270 // Output
271 if (verbosity_ > 0) writeOutput(outStream,true);
272
273 while (status_->check(*state_)) {
274 // Build trust-region model
275 model_->setData(obj,*state_->iterateVec,*state_->gradientVec,gtol_);
276
277 /**** SOLVE TRUST-REGION SUBPROBLEM ****/
278 // Compute Cauchy point (TRON notation: x = x[1])
279 snorm = dcauchy(*state_->stepVec,alpha_,q,*state_->iterateVec,
280 state_->gradientVec->dual(),state_->searchSize,
281 *model_,*dwa1,*dwa2,outStream); // Solve 1D optimization problem for alpha
282 x.plus(*state_->stepVec); // Set x = x[0] + alpha*g
283 state_->snorm = snorm;
284 delta = state_->searchSize - snorm;
285 pRed = -q;
286
287 // Model gradient at s = x[1] - x[0]
288 gmod->set(*dwa1); // hessVec from Cauchy point computation
289 gmod->plus(*state_->gradientVec);
290 gfree->set(*gmod);
291 //bnd.pruneActive(*gfree,x,zero);
292 pwa1->set(gfree->dual());
293 bnd.pruneActive(*pwa1,x,zero);
294 gfree->set(pwa1->dual());
295 if (hasEcon_) {
296 applyFreePrecond(*pwa1,*gfree,x,*model_,bnd,tol0,*dwa1,*pwa2);
297 gfnorm = pwa1->norm();
298 }
299 else {
300 gfnorm = gfree->norm();
301 }
302 SPiter_ = 0; SPflag_ = 0;
303 if (verbosity_ > 1) {
304 outStream << " Norm of free gradient components: " << gfnorm << std::endl;
305 outStream << std::endl;
306 }
307
308 // Trust-region subproblem solve loop
309 maxit = maxit_;
310 for (int i = 0; i < minit_; ++i) {
311 // Run Truncated CG
312 flagCG = 0; iterCG = 0;
313 gfnormf = zero;
314 tol = std::min(tol1_,tol2_*std::pow(gfnorm,spexp_));
315 stol = tol; //zero;
316 if (gfnorm > zero && delta > zero) {
317 snorm = dtrpcg(*s,flagCG,iterCG,*gfree,x,
318 delta,*model_,bnd,tol,stol,maxit,
319 *pwa1,*dwa1,*pwa2,*dwa2,*pwa3,*dwa3,outStream);
320 maxit -= iterCG;
321 SPiter_ += iterCG;
322 if (verbosity_ > 1) {
323 outStream << " Computation of CG step" << std::endl;
324 outStream << " Current face (i): " << i << std::endl;
325 outStream << " CG step length: " << snorm << std::endl;
326 outStream << " Number of CG iterations: " << iterCG << std::endl;
327 outStream << " CG flag: " << flagCG << std::endl;
328 outStream << " Total number of iterations: " << SPiter_ << std::endl;
329 outStream << std::endl;
330 }
331
332 // Projected search
333 snorm = dprsrch(x,*s,q,gmod->dual(),*model_,bnd,*pwa1,*dwa1,outStream);
334 pRed += -q;
335
336 // Model gradient at s = (x[i+1]-x[i]) - (x[i]-x[0])
337 state_->stepVec->plus(*s);
338 state_->snorm = state_->stepVec->norm();
339 delta = state_->searchSize - state_->snorm;
340 gmod->plus(*dwa1); // gmod = H(x[i+1]-x[i]) + H(x[i]-x[0]) + g
341 gfree->set(*gmod);
342 //bnd.pruneActive(*gfree,x,zero);
343 pwa1->set(gfree->dual());
344 bnd.pruneActive(*pwa1,x,zero);
345 gfree->set(pwa1->dual());
346 if (hasEcon_) {
347 applyFreePrecond(*pwa1,*gfree,x,*model_,bnd,tol0,*dwa1,*pwa2);
348 gfnormf = pwa1->norm();
349 }
350 else {
351 gfnormf = gfree->norm();
352 }
353 if (verbosity_ > 1) {
354 outStream << " Norm of free gradient components: " << gfnormf << std::endl;
355 outStream << std::endl;
356 }
357 }
358
359 // Termination check
360 if (gfnormf <= tol) {
361 SPflag_ = 0;
362 break;
363 }
364 else if (SPiter_ >= maxit_) {
365 SPflag_ = 1;
366 break;
367 }
368 else if (flagCG == 2) {
369 SPflag_ = 2;
370 break;
371 }
372 else if (delta <= zero) {
373 //else if (flagCG == 3 || delta <= zero) {
374 SPflag_ = 3;
375 break;
376 }
377
378 // Update free gradient norm
379 gfnorm = gfnormf;
380 }
381
382 // Compute trial objective value
383 //obj.update(x,UpdateType::Trial);
384 //ftrial = obj.value(x,tol0);
385 ftrial = computeValue(inTol,outTol,pRed,state_->value,state_->iter,x,*state_->iterateVec,obj);
386 state_->nfval++;
387
388 // Compute ratio of acutal and predicted reduction
390 TRUtils::analyzeRatio<Real>(rho,TRflag_,state_->value,ftrial,pRed,eps_,outStream,verbosity_>1);
391 if (useNM_) {
392 TRUtils::analyzeRatio<Real>(rhoNM,TRflagNM,fr,ftrial,pRed+sigmar,eps_,outStream,verbosity_>1);
393 TRflag_ = (rho < rhoNM ? TRflagNM : TRflag_);
394 rho = (rho < rhoNM ? rhoNM : rho );
395 }
396
397 // Update algorithm state
398 state_->iter++;
399 // Accept/reject step and update trust region radius
400 if ((rho < eta0_ && TRflag_ == TRUtils::SUCCESS) || (TRflag_ >= 2)) { // Step Rejected
401 x.set(*state_->iterateVec);
402 obj.update(x,UpdateType::Revert,state_->iter);
403 if (interpRad_ && (rho < zero && TRflag_ != TRUtils::TRNAN)) {
404 // Negative reduction, interpolate to find new trust-region radius
405 state_->searchSize = TRUtils::interpolateRadius<Real>(*state_->gradientVec,*state_->stepVec,
406 state_->snorm,pRed,state_->value,ftrial,state_->searchSize,gamma0_,gamma1_,eta2_,
407 outStream,verbosity_>1);
408 }
409 else { // Shrink trust-region radius
410 state_->searchSize = gamma1_*std::min(state_->snorm,state_->searchSize);
411 }
412 computeGradient(x,*state_->gradientVec,*pwa1,state_->searchSize,obj,false,gtol_,state_->gnorm,outStream);
413 }
414 else if ((rho >= eta0_ && TRflag_ != TRUtils::NPOSPREDNEG)
415 || (TRflag_ == TRUtils::POSPREDNEG)) { // Step Accepted
416 state_->value = ftrial;
417 obj.update(x,UpdateType::Accept,state_->iter);
418 if (useNM_) {
419 sigmac += pRed; sigmar += pRed;
420 if (ftrial < fmin) { fmin = ftrial; fc = fmin; sigmac = zero; L = 0; }
421 else {
422 L++;
423 if (ftrial > fc) { fc = ftrial; sigmac = zero; }
424 if (L == storageNM_) { fr = fc; sigmar = sigmac; }
425 }
426 }
427 // Increase trust-region radius
428 if (rho >= eta2_) state_->searchSize = std::min(gamma2_*state_->searchSize, delMax_);
429 // Compute gradient at new iterate
430 dwa1->set(*state_->gradientVec);
431 //obj.gradient(*state_->gradientVec,x,tol0);
432 computeGradient(x,*state_->gradientVec,*pwa1,state_->searchSize,obj,true,gtol_,state_->gnorm,outStream);
433 state_->ngrad++;
434 //state_->gnorm = TypeB::Algorithm<Real>::optimalityCriterion(x,*state_->gradientVec,*pwa1,outStream);
435 state_->iterateVec->set(x);
436 // Update secant information in trust-region model
437 model_->update(x,*state_->stepVec,*dwa1,*state_->gradientVec,
438 state_->snorm,state_->iter);
439 }
440
441 // Update Output
442 if (verbosity_ > 0) writeOutput(outStream,writeHeader_);
443 }
445}
446
447template<typename Real>
449 const Vector<Real> &x, const Real alpha,
450 std::ostream &outStream) const {
451 s.set(x); s.axpy(alpha,w);
452 proj_->project(s,outStream); state_->nproj++;
453 s.axpy(static_cast<Real>(-1),x);
454 return s.norm();
455}
456
457template<typename Real>
459 Real &alpha,
460 Real &q,
461 const Vector<Real> &x,
462 const Vector<Real> &g,
463 const Real del,
465 Vector<Real> &dwa, Vector<Real> &dwa1,
466 std::ostream &outStream) {
467 const Real half(0.5);
468 Real tol = std::sqrt(ROL_EPSILON<Real>());
469 bool interp = false;
470 Real gs(0), snorm(0);
471 // Compute s = P(x[0] - alpha g[0])
472 snorm = dgpstep(s,g,x,-alpha,outStream);
473 if (snorm > del) {
474 interp = true;
475 }
476 else {
477 model.hessVec(dwa,s,x,tol); nhess_++;
478 gs = s.dot(g);
479 q = half * s.apply(dwa) + gs;
480 interp = (q > mu0_*gs);
481 }
482 // Either increase or decrease alpha to find approximate Cauchy point
483 int cnt = 0;
484 if (interp) {
485 bool search = true;
486 while (search && cnt < redlim_) {
487 alpha *= interpf_;
488 snorm = dgpstep(s,g,x,-alpha,outStream);
489 if (snorm <= del) {
490 model.hessVec(dwa,s,x,tol); nhess_++;
491 gs = s.dot(g);
492 q = half * s.apply(dwa) + gs;
493 search = (q > mu0_*gs);
494 }
495 cnt++;
496 }
497 if (cnt >= redlim_ && q > mu0_*gs) {
498 outStream << "Cauchy point: The interpolation limit was met without producing sufficient decrease." << std::endl;
499 outStream << " Lin-More trust-region algorithm may not converge!" << std::endl;
500 }
501 }
502 else {
503 bool search = true;
504 Real alphas = alpha;
505 Real qs = q;
506 dwa1.set(dwa);
507 while (search) {
508 alpha *= extrapf_;
509 snorm = dgpstep(s,g,x,-alpha,outStream);
510 if (snorm <= del && cnt < explim_) {
511 model.hessVec(dwa,s,x,tol); nhess_++;
512 gs = s.dot(g);
513 q = half * s.apply(dwa) + gs;
514 if (q <= mu0_*gs && std::abs(q-qs) > qtol_*std::abs(qs)) {
515 dwa1.set(dwa);
516 search = true;
517 alphas = alpha;
518 qs = q;
519 }
520 else {
521 q = qs;
522 dwa.set(dwa1);
523 search = false;
524 }
525 }
526 else {
527 search = false;
528 }
529 cnt++;
530 }
531 alpha = alphas;
532 snorm = dgpstep(s,g,x,-alpha,outStream);
533 }
534 if (verbosity_ > 1) {
535 outStream << " Cauchy point" << std::endl;
536 outStream << " Step length (alpha): " << alpha << std::endl;
537 outStream << " Step length (alpha*g): " << snorm << std::endl;
538 outStream << " Model decrease (pRed): " << -q << std::endl;
539 if (!interp) {
540 outStream << " Number of extrapolation steps: " << cnt << std::endl;
541 }
542 }
543 return snorm;
544}
545
546template<typename Real>
548 Real &q, const Vector<Real> &g,
551 Vector<Real> &pwa, Vector<Real> &dwa,
552 std::ostream &outStream) {
553 const Real zero(0.0), half(0.5);
554 Real tol = std::sqrt(ROL_EPSILON<Real>());
555 Real beta(1), snorm(0), gs(0);
556 int nsteps = 0;
557 // Reduce beta until sufficient decrease is satisfied
558 bool search = true;
559 while (search) {
560 nsteps++;
561 snorm = dgpstep(pwa,s,x,beta,outStream);
562 model.hessVec(dwa,pwa,x,tol); nhess_++;
563 gs = pwa.dot(g);
564 //q = half * pwa.dot(dwa.dual()) + gs;
565 q = half * pwa.apply(dwa) + gs;
566 if (q <= mu0_*std::min(gs,zero) || nsteps > pslim_) {
567 search = false;
568 }
569 else {
570 beta *= interpfPS_;
571 }
572 }
573 s.set(pwa);
574 x.plus(s);
575 if (verbosity_ > 1) {
576 outStream << std::endl;
577 outStream << " Projected search" << std::endl;
578 outStream << " Step length (beta): " << beta << std::endl;
579 outStream << " Step length (beta*s): " << snorm << std::endl;
580 outStream << " Model decrease (pRed): " << -q << std::endl;
581 outStream << " Number of steps: " << nsteps << std::endl;
582 }
583 return snorm;
584}
585
586template<typename Real>
588 const Real ptp,
589 const Real ptx,
590 const Real del) const {
591 const Real zero(0);
592 Real dsq = del*del;
593 Real rad = ptx*ptx + ptp*(dsq-xtx);
594 rad = std::sqrt(std::max(rad,zero));
595 Real sigma(0);
596 if (ptx > zero) {
597 sigma = (dsq-xtx)/(ptx+rad);
598 }
599 else if (rad > zero) {
600 sigma = (rad-ptx)/ptp;
601 }
602 else {
603 sigma = zero;
604 }
605 return sigma;
606}
607
608template<typename Real>
609Real LinMoreAlgorithm<Real>::dtrpcg(Vector<Real> &w, int &iflag, int &iter,
610 const Vector<Real> &g, const Vector<Real> &x,
611 const Real del, TrustRegionModel_U<Real> &model,
613 const Real tol, const Real stol, const int itermax,
616 std::ostream &outStream) const {
617 // p = step (primal)
618 // q = hessian applied to step p (dual)
619 // t = gradient (dual)
620 // r = preconditioned gradient (primal)
621 Real tol0 = std::sqrt(ROL_EPSILON<Real>());
622 const Real zero(0), one(1), two(2);
623 Real rho(0), kappa(0), beta(0), sigma(0), alpha(0);
624 Real rtr(0), tnorm(0), sMs(0), pMp(0), sMp(0);
625 iter = 0; iflag = 0;
626 // Initialize step
627 w.zero();
628 // Compute residual
629 t.set(g); t.scale(-one);
630 // Preconditioned residual
631 applyFreePrecond(r,t,x,model,bnd,tol0,dwa,pwa);
632 //rho = r.dot(t.dual());
633 rho = r.apply(t);
634 // Initialize direction
635 p.set(r);
636 pMp = (!hasEcon_ ? rho : p.dot(p)); // If no equality constraint, used preconditioned norm
637 // Iterate CG
638 for (iter = 0; iter < itermax; ++iter) {
639 // Apply Hessian to direction dir
640 applyFreeHessian(q,p,x,model,bnd,tol0,pwa);
641 // Compute sigma such that ||s+sigma*dir|| = del
642 //kappa = p.dot(q.dual());
643 kappa = p.apply(q);
644 alpha = (kappa>zero) ? rho/kappa : zero;
645 sigma = dtrqsol(sMs,pMp,sMp,del);
646 // Check for negative curvature or if iterate exceeds trust region
647 if (kappa <= zero || alpha >= sigma) {
648 w.axpy(sigma,p);
649 sMs = del*del;
650 iflag = (kappa<=zero) ? 2 : 3;
651 break;
652 }
653 // Update iterate and residuals
654 w.axpy(alpha,p);
655 t.axpy(-alpha,q);
656 applyFreePrecond(r,t,x,model,bnd,tol0,dwa,pwa);
657 // Exit if residual tolerance is met
658 //rtr = r.dot(t.dual());
659 rtr = r.apply(t);
660 tnorm = t.norm();
661 if (rtr <= stol*stol || tnorm <= tol) {
662 sMs = sMs + two*alpha*sMp + alpha*alpha*pMp;
663 iflag = 0;
664 break;
665 }
666 // Compute p = r + beta * p
667 beta = rtr/rho;
668 p.scale(beta); p.plus(r);
669 rho = rtr;
670 // Update dot products
671 // sMs = <s, inv(M)s> or <s, s> if equality constraint present
672 // sMp = <s, inv(M)p> or <s, p> if equality constraint present
673 // pMp = <p, inv(M)p> or <p, p> if equality constraint present
674 sMs = sMs + two*alpha*sMp + alpha*alpha*pMp;
675 sMp = beta*(sMp + alpha*pMp);
676 pMp = (!hasEcon_ ? rho : p.dot(p)) + beta*beta*pMp;
677 }
678 // Check iteration count
679 if (iter == itermax) {
680 iflag = 1;
681 }
682 if (iflag != 1) {
683 iter++;
684 }
685 return std::sqrt(sMs); // w.norm();
686}
687
688template<typename Real>
690 const Vector<Real> &v,
691 const Vector<Real> &x,
694 Real &tol,
695 Vector<Real> &pwa) const {
696 const Real zero(0);
697 pwa.set(v);
698 bnd.pruneActive(pwa,x,zero);
699 model.hessVec(hv,pwa,x,tol); nhess_++;
700 pwa.set(hv.dual());
701 bnd.pruneActive(pwa,x,zero);
702 hv.set(pwa.dual());
703 //pwa.set(v);
704 //bnd.pruneActive(pwa,x,zero);
705 //model.hessVec(hv,pwa,x,tol); nhess_++;
706 //bnd.pruneActive(hv,x,zero);
707}
708
709template<typename Real>
711 const Vector<Real> &v,
712 const Vector<Real> &x,
715 Real &tol,
716 Vector<Real> &dwa,
717 Vector<Real> &pwa) const {
718 if (!hasEcon_) {
719 const Real zero(0);
720 pwa.set(v.dual());
721 bnd.pruneActive(pwa,x,zero);
722 dwa.set(pwa.dual());
723 model.precond(hv,dwa,x,tol);
724 bnd.pruneActive(hv,x,zero);
725 //dwa.set(v);
726 //bnd.pruneActive(dwa,x,zero);
727 //model.precond(hv,dwa,x,tol);
728 //bnd.pruneActive(hv,x,zero);
729 }
730 else {
731 // Perform null space projection
732 rcon_->setX(makePtrFromRef(x));
733 ns_->update(x);
734 pwa.set(v.dual());
735 ns_->apply(hv,pwa,tol);
736 }
737}
738
739template<typename Real>
740void LinMoreAlgorithm<Real>::writeHeader( std::ostream& os ) const {
741 std::ios_base::fmtflags osFlags(os.flags());
742 if (verbosity_ > 1) {
743 os << std::string(114,'-') << std::endl;
744 os << " Lin-More trust-region method status output definitions" << std::endl << std::endl;
745 os << " iter - Number of iterates (steps taken)" << std::endl;
746 os << " value - Objective function value" << std::endl;
747 os << " gnorm - Norm of the gradient" << std::endl;
748 os << " snorm - Norm of the step (update to optimization vector)" << std::endl;
749 os << " delta - Trust-Region radius" << std::endl;
750 os << " #fval - Number of times the objective function was evaluated" << std::endl;
751 os << " #grad - Number of times the gradient was computed" << std::endl;
752 os << " #hess - Number of times the Hessian was applied" << std::endl;
753 os << " #proj - Number of times the projection was applied" << std::endl;
754 os << std::endl;
755 os << " tr_flag - Trust-Region flag" << std::endl;
756 for( int flag = TRUtils::SUCCESS; flag != TRUtils::UNDEFINED; ++flag ) {
757 os << " " << NumberToString(flag) << " - "
758 << TRUtils::ETRFlagToString(static_cast<TRUtils::ETRFlag>(flag)) << std::endl;
759 }
760 os << std::endl;
761 if (minit_ > 0) {
762 os << " iterCG - Number of Truncated CG iterations" << std::endl << std::endl;
763 os << " flagGC - Trust-Region Truncated CG flag" << std::endl;
764 for( int flag = CG_FLAG_SUCCESS; flag != CG_FLAG_UNDEFINED; ++flag ) {
765 os << " " << NumberToString(flag) << " - "
766 << ECGFlagToString(static_cast<ECGFlag>(flag)) << std::endl;
767 }
768 }
769 os << std::string(114,'-') << std::endl;
770 }
771 os << " ";
772 os << std::setw(6) << std::left << "iter";
773 os << std::setw(15) << std::left << "value";
774 os << std::setw(15) << std::left << "gnorm";
775 os << std::setw(15) << std::left << "snorm";
776 os << std::setw(15) << std::left << "delta";
777 os << std::setw(10) << std::left << "#fval";
778 os << std::setw(10) << std::left << "#grad";
779 os << std::setw(10) << std::left << "#hess";
780 os << std::setw(10) << std::left << "#proj";
781 os << std::setw(10) << std::left << "tr_flag";
782 if (minit_ > 0) {
783 os << std::setw(10) << std::left << "iterCG";
784 os << std::setw(10) << std::left << "flagCG";
785 }
786 os << std::endl;
787 os.flags(osFlags);
788}
789
790template<typename Real>
791void LinMoreAlgorithm<Real>::writeName( std::ostream& os ) const {
792 std::ios_base::fmtflags osFlags(os.flags());
793 os << std::endl << "Lin-More Trust-Region Method (Type B, Bound Constraints)" << std::endl;
794 os.flags(osFlags);
795}
796
797template<typename Real>
798void LinMoreAlgorithm<Real>::writeOutput( std::ostream& os, bool write_header ) const {
799 std::ios_base::fmtflags osFlags(os.flags());
800 os << std::scientific << std::setprecision(6);
801 if ( state_->iter == 0 ) writeName(os);
802 if ( write_header ) writeHeader(os);
803 if ( state_->iter == 0 ) {
804 os << " ";
805 os << std::setw(6) << std::left << state_->iter;
806 os << std::setw(15) << std::left << state_->value;
807 os << std::setw(15) << std::left << state_->gnorm;
808 os << std::setw(15) << std::left << "---";
809 os << std::setw(15) << std::left << state_->searchSize;
810 os << std::setw(10) << std::left << state_->nfval;
811 os << std::setw(10) << std::left << state_->ngrad;
812 os << std::setw(10) << std::left << nhess_;
813 os << std::setw(10) << std::left << state_->nproj;
814 os << std::setw(10) << std::left << "---";
815 if (minit_ > 0) {
816 os << std::setw(10) << std::left << "---";
817 os << std::setw(10) << std::left << "---";
818 }
819 os << std::endl;
820 }
821 else {
822 os << " ";
823 os << std::setw(6) << std::left << state_->iter;
824 os << std::setw(15) << std::left << state_->value;
825 os << std::setw(15) << std::left << state_->gnorm;
826 os << std::setw(15) << std::left << state_->snorm;
827 os << std::setw(15) << std::left << state_->searchSize;
828 os << std::setw(10) << std::left << state_->nfval;
829 os << std::setw(10) << std::left << state_->ngrad;
830 os << std::setw(10) << std::left << nhess_;
831 os << std::setw(10) << std::left << state_->nproj;
832 os << std::setw(10) << std::left << TRflag_;
833 if (minit_ > 0) {
834 os << std::setw(10) << std::left << SPiter_;
835 os << std::setw(10) << std::left << SPflag_;
836 }
837 os << std::endl;
838 }
839 os.flags(osFlags);
840}
841
842} // namespace TypeB
843} // namespace ROL
844
845#endif
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0 zero)()
virtual void initialize(const Vector< Real > &x)
Initialize temporary variables.
Provides the interface to apply upper and lower bound constraints.
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 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 an interface to check status of optimization algorithms.
Provides the interface to evaluate trust-region model functions.
virtual void hessVec(Vector< Real > &hv, const Vector< Real > &v, const Vector< Real > &s, Real &tol) override
virtual void precond(Vector< Real > &Pv, const Vector< Real > &v, const Vector< Real > &s, Real &tol) override
Ptr< PolyhedralProjection< Real > > proj_
void initialize(const Vector< Real > &x, const Vector< Real > &g)
Real optimalityCriterion(const Vector< Real > &x, const Vector< Real > &g, Vector< Real > &primal, std::ostream &outStream=std::cout) const
virtual void writeExitStatus(std::ostream &os) const
const Ptr< AlgorithmState< Real > > state_
const Ptr< CombinedStatusTest< Real > > status_
void writeOutput(std::ostream &os, const bool write_header=false) const override
Print iterate status.
bool useSecantHessVec_
Flag to use secant as Hessian (default: false).
Real alpha_
Initial Cauchy point step length (default: 1.0).
Real interpfPS_
Backtracking rate for projected search (default: 0.5).
Ptr< ReducedLinearConstraint< Real > > rcon_
Equality constraint restricted to current active variables.
Real eta1_
Radius decrease threshold (default: 0.05).
void initialize(Vector< Real > &x, const Vector< Real > &g, Objective< Real > &obj, BoundConstraint< Real > &bnd, std::ostream &outStream=std::cout)
Real TRsafe_
Safeguard size for numerically evaluating ratio (default: 1e2).
void applyFreeHessian(Vector< Real > &hv, const Vector< Real > &v, const Vector< Real > &x, TrustRegionModel_U< Real > &model, BoundConstraint< Real > &bnd, Real &tol, Vector< Real > &pwa) const
Real dcauchy(Vector< Real > &s, Real &alpha, Real &q, const Vector< Real > &x, const Vector< Real > &g, const Real del, TrustRegionModel_U< Real > &model, Vector< Real > &dwa, Vector< Real > &dwa1, std::ostream &outStream=std::cout)
bool writeHeader_
Flag to write header at every iteration.
bool hasEcon_
Flag signifies if equality constraints exist.
Real tol1_
Absolute tolerance for truncated CG (default: 1e-4).
Real spexp_
Relative tolerance exponent for subproblem solve (default: 1, range: [1,2]).
void run(Vector< Real > &x, const Vector< Real > &g, Objective< Real > &obj, BoundConstraint< Real > &bnd, std::ostream &outStream=std::cout) override
Run algorithm on bound constrained problems (Type-B). This general interface supports the use of dual...
Real dtrqsol(const Real xtx, const Real ptp, const Real ptx, const Real del) const
int nhess_
Number of Hessian applications.
Real mu0_
Sufficient decrease parameter (default: 1e-2).
Real dtrpcg(Vector< Real > &w, int &iflag, int &iter, const Vector< Real > &g, const Vector< Real > &x, const Real del, TrustRegionModel_U< Real > &model, BoundConstraint< Real > &bnd, const Real tol, const Real stol, const int itermax, Vector< Real > &p, Vector< Real > &q, Vector< Real > &r, Vector< Real > &t, Vector< Real > &pwa, Vector< Real > &dwa, std::ostream &outStream=std::cout) const
void applyFreePrecond(Vector< Real > &hv, const Vector< Real > &v, const Vector< Real > &x, TrustRegionModel_U< Real > &model, BoundConstraint< Real > &bnd, Real &tol, Vector< Real > &dwa, Vector< Real > &pwa) const
Real eta0_
Step acceptance threshold (default: 0.05).
int SPflag_
Subproblem solver termination flag.
Ptr< TrustRegionModel_U< Real > > model_
Container for trust-region model.
Real interpf_
Backtracking rate for Cauchy point computation (default: 1e-1).
int minit_
Maximum number of minor (subproblem solve) iterations (default: 10).
int maxit_
Maximum number of CG iterations (default: 20).
bool normAlpha_
Normalize initial Cauchy point step length (default: false).
bool interpRad_
Interpolate the trust-region radius if ratio is negative (default: false).
Real qtol_
Relative tolerance for computed decrease in Cauchy point computation (default: 1-8).
Real tol2_
Relative tolerance for truncated CG (default: 1e-2).
Real gamma1_
Radius decrease rate (positive rho) (default: 0.25).
Real dprsrch(Vector< Real > &x, Vector< Real > &s, Real &q, const Vector< Real > &g, TrustRegionModel_U< Real > &model, BoundConstraint< Real > &bnd, Vector< Real > &pwa, Vector< Real > &dwa, std::ostream &outStream=std::cout)
Real gamma2_
Radius increase rate (default: 2.5).
Real gamma0_
Radius decrease rate (negative rho) (default: 0.0625).
Real eps_
Safeguard for numerically evaluating ratio.
Real delMax_
Maximum trust-region radius (default: ROL_INF).
void writeName(std::ostream &os) const override
Print step name.
unsigned verbosity_
Output level (default: 0).
ESecant esec_
Secant type (default: Limited-Memory BFGS).
Real eta2_
Radius increase threshold (default: 0.9).
Real extrapf_
Extrapolation rate for Cauchy point computation (default: 1e1).
TRUtils::ETRFlag TRflag_
Trust-region exit flag.
bool useSecantPrecond_
Flag to use secant as a preconditioner (default: false).
int redlim_
Maximum number of Cauchy point reduction steps (default: 10).
void computeGradient(const Vector< Real > &x, Vector< Real > &g, Vector< Real > &pwa, Real del, Objective< Real > &obj, bool accept, Real &gtol, Real &gnorm, std::ostream &outStream=std::cout) const
Real dgpstep(Vector< Real > &s, const Vector< Real > &w, const Vector< Real > &x, const Real alpha, std::ostream &outStream=std::cout) const
int pslim_
Maximum number of projected search steps (default: 20).
Ptr< NullSpaceOperator< Real > > ns_
Null space projection onto reduced equality constraint Jacobian.
LinMoreAlgorithm(ParameterList &list, const Ptr< Secant< Real > > &secant=nullPtr)
int SPiter_
Subproblem solver iteration count.
void writeHeader(std::ostream &os) const override
Print iterate header.
int explim_
Maximum number of Cauchy point expansion steps (default: 10).
Real computeValue(Real inTol, Real &outTol, Real pRed, Real &fold, int iter, const Vector< Real > &x, const Vector< Real > &xold, Objective< Real > &obj)
Defines the linear algebra or vector space interface.
virtual Real apply(const Vector< Real > &x) const
Apply to a dual vector. This is equivalent to the call .
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 void zero()
Set to zero vector.
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 .
void analyzeRatio(Real &rho, ETRFlag &flag, const Real fold, const Real ftrial, const Real pRed, const Real epsi, std::ostream &outStream=std::cout, const bool print=false)
std::string ETRFlagToString(ETRFlag trf)
Real interpolateRadius(const Vector< Real > &g, const Vector< Real > &s, const Real snorm, const Real pRed, const Real fold, const Real ftrial, const Real del, const Real gamma0, const Real gamma1, const Real eta2, std::ostream &outStream=std::cout, const bool print=false)
std::string NumberToString(T Number)
Definition ROL_Types.hpp:47
Real ROL_EPSILON(void)
Platform-dependent machine epsilon.
Definition ROL_Types.hpp:57
ESecant StringToESecant(std::string s)
ESecantMode
@ SECANTMODE_FORWARD
@ SECANTMODE_INVERSE
@ SECANTMODE_BOTH
@ CG_FLAG_UNDEFINED
@ CG_FLAG_SUCCESS
Real ROL_OVERFLOW(void)
Platform-dependent maximum double.
Definition ROL_Types.hpp:68
std::string ECGFlagToString(ECGFlag cgf)
Real ROL_INF(void)
Definition ROL_Types.hpp:71