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