ROL
ROL_FletcherStep.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_FLETCHERSTEP_H
11 #define ROL_FLETCHERSTEP_H
12 
13 #include "ROL_FletcherBase.hpp"
14 #include "ROL_Step.hpp"
15 #include "ROL_TrustRegionStep.hpp"
16 #include "ROL_LineSearchStep.hpp"
17 #include "ROL_Types.hpp"
18 #include "ROL_ParameterList.hpp"
25 namespace ROL {
26 
27 template <class Real>
28 class FletcherStep : public Step<Real> {
29 private:
30  ROL::Ptr<Step<Real> > step_;
31  ROL::Ptr<BoundConstraint<Real> > bnd_;
32 
33  ROL::ParameterList parlist_;
34 
35  ROL::Ptr<Vector<Real> > x_;
36 
37  // Lagrange multiplier update
42  // Subproblem information
43  bool print_;
44  std::string subStep_;
45 
46  Real delta_;
47  Real deltaMin_;
50 
52 
53  ROL::Ptr<Vector<Real> > g_;
54 
56 
57  // For printing output
58  mutable bool isDeltaChanged_;
59  mutable bool isPenaltyChanged_;
60 
62 
63  mutable int stepHeaderLength_; // For formatting
64 
66  BoundConstraint<Real> &bnd) {
67  Real gnorm = 0.;
68  // Compute norm of projected gradient
69  if (bnd.isActivated()) {
70  x_->set(x);
71  x_->axpy(-1.,g.dual());
72  bnd.project(*x_);
73  x_->axpy(-1.,x);
74  gnorm = x_->norm();
75  }
76  else {
77  gnorm = g.norm();
78  }
79  return gnorm;
80  }
81 
82 public:
83 
85  using Step<Real>::compute;
86  using Step<Real>::update;
87 
89 
90  FletcherStep(ROL::ParameterList &parlist)
91  : Step<Real>(), bnd_activated_(false), numSuccessSteps_(0),
93  Real zero(0), one(1), two(2), oe8(1.e8), oe1(1.e-1), oem6(1e-6), oem8(1.e-8);
94 
95  ROL::ParameterList& sublist = parlist.sublist("Step").sublist("Fletcher");
96  Step<Real>::getState()->searchSize = sublist.get("Penalty Parameter",one);
97  delta_ = sublist.get("Regularization Parameter",zero);
98  deltaMin_ = sublist.get("Min Regularization Parameter",oem8);
99  deltaUpdate_ = sublist.get("Regularization Parameter Decrease Factor", oe1);
100  // penalty parameters
101  penaltyUpdate_ = sublist.get("Penalty Parameter Growth Factor", two);
102  modifyPenalty_ = sublist.get("Modify Penalty Parameter", false);
103  maxPenaltyParam_ = sublist.get("Maximum Penalty Parameter", oe8);
104  minPenaltyParam_ = sublist.get("Minimum Penalty Parameter", oem6);
105 
106  subStep_ = sublist.get("Subproblem Solver", "Trust Region");
107 
108  parlist_ = parlist;
109  }
110 
115  AlgorithmState<Real> &algo_state ) {
116  bnd_ = ROL::makePtr<BoundConstraint<Real>>();
117  bnd_->deactivate();
118  initialize(x,g,l,c,obj,con,*bnd_,algo_state);
119  }
120 
125  AlgorithmState<Real> &algo_state ) {
126  // Determine what kind of step
127  bnd_activated_ = bnd.isActivated();
128 
129  ROL::ParameterList trlist(parlist_);
130  bool inexactFletcher = trlist.sublist("Step").sublist("Fletcher").get("Inexact Solves", false);
131  if( inexactFletcher ) {
132  trlist.sublist("General").set("Inexact Objective Value", true);
133  trlist.sublist("General").set("Inexact Gradient", true);
134  }
135  if( bnd_activated_ ) {
136  trlist.sublist("Step").sublist("Trust Region").set("Subproblem Model", "Coleman-Li");
137  }
138 
139  if ( subStep_ == "Line Search" ) {
140  step_ = makePtr<LineSearchStep<Real>>(trlist);
141  }
142  else {
143  step_ = makePtr<TrustRegionStep<Real>>(trlist);
144  }
145  etr_ = StringToETrustRegion(parlist_.sublist("Step").sublist("Trust Region").get("Subproblem Solver", "Truncated CG"));
146 
147  // Initialize class members
148  g_ = g.clone();
149  x_ = x.clone();
150 
151  // Rest of initialize
152  FletcherBase<Real>& fletcher = dynamic_cast<FletcherBase<Real>&>(obj);
153 
154  tr_algo_state_.iterateVec = x.clone();
155  tr_algo_state_.minIterVec = x.clone();
156  tr_algo_state_.lagmultVec = l.clone();
157 
158  step_->initialize(x, g, obj, bnd, tr_algo_state_);
159 
160  // Initialize step state
161  ROL::Ptr<StepState<Real> > state = Step<Real>::getState();
162  state->descentVec = x.clone();
163  state->gradientVec = g.clone();
164  state->constraintVec = c.clone();
165  // Initialize the algorithm state
166  algo_state.nfval = 0;
167  algo_state.ncval = 0;
168  algo_state.ngrad = 0;
169 
170  algo_state.value = fletcher.getObjectiveValue(x);
171  algo_state.gnorm = computeProjGradientNorm(*(fletcher.getLagrangianGradient(x)),
172  x, bnd);
173  algo_state.aggregateGradientNorm = tr_algo_state_.gnorm;
174 
175  state->constraintVec->set(*(fletcher.getConstraintVec(x)));
176  algo_state.cnorm = (state->constraintVec)->norm();
177  // Update evaluation counters
178  algo_state.ncval = fletcher.getNumberConstraintEvaluations();
179  algo_state.nfval = fletcher.getNumberFunctionEvaluations();
180  algo_state.ngrad = fletcher.getNumberGradientEvaluations();
181  }
182 
185  void compute( Vector<Real> &s, const Vector<Real> &x, const Vector<Real> &l,
186  Objective<Real> &obj, Constraint<Real> &con,
187  AlgorithmState<Real> &algo_state ) {
188  compute(s,x,l,obj,con,*bnd_, algo_state);
189  }
190 
193  void compute( Vector<Real> &s, const Vector<Real> &x, const Vector<Real> &l,
194  Objective<Real> &obj, Constraint<Real> &con,
195  BoundConstraint<Real> &bnd, AlgorithmState<Real> &algo_state ) {
196  step_->compute( s, x, obj, bnd, tr_algo_state_ );
197  }
198 
203  AlgorithmState<Real> &algo_state ) {
204  update(x,l,s,obj,con,*bnd_, algo_state);
205  }
206 
212  AlgorithmState<Real> &algo_state ) {
213 
214  // This should be in print, but this will not work there
215  isDeltaChanged_ = false;
216  isPenaltyChanged_ = false;
217  bool modified = false;
218 
219  FletcherBase<Real> &fletcher = dynamic_cast<FletcherBase<Real>&>(obj);
220  ROL::Ptr<StepState<Real> > fletcherState = Step<Real>::getState();
221  const ROL::Ptr<const StepState<Real> > state = step_->getStepState();
222 
223  step_->update(x,s,obj,bnd,tr_algo_state_);
224  numSuccessSteps_ += (state->flag == 0);
225 
226  Real gPhiNorm = tr_algo_state_.gnorm;
227  Real cnorm = (fletcherState->constraintVec)->norm();
228  bool too_infeasible = cnorm > static_cast<Real>(100.)*gPhiNorm;
229  bool too_feasible = cnorm < static_cast<Real>(1e-2)*gPhiNorm;
230 
231  if( too_infeasible && !modified && modifyPenalty_ && numSuccessSteps_ > 1 ) {
232  Real penaltyParam = Step<Real>::getStepState()->searchSize;
233  if( penaltyParam >= maxPenaltyParam_ ) {
234  // Penalty parameter too large, exit
235  algo_state.flag = true;
236  }
237  penaltyParam *= penaltyUpdate_;
238  penaltyParam = std::min(penaltyParam, maxPenaltyParam_);
239  fletcher.setPenaltyParameter(penaltyParam);
240  Step<Real>::getState()->searchSize = penaltyParam;
241  isPenaltyChanged_ = true;
242  modified = true;
243  }
244 
245  if( too_feasible && !modified && modifyPenalty_ && numSuccessSteps_ > 1 ) {
246  Real penaltyParam = Step<Real>::getStepState()->searchSize;
247  if( penaltyParam <= minPenaltyParam_ ) {
248  // Penalty parameter too small, exit (this is unlikely)
249  algo_state.flag = true;
250  }
251  penaltyParam /= penaltyUpdate_;
252  penaltyParam = std::max(penaltyParam, minPenaltyParam_);
253  fletcher.setPenaltyParameter(penaltyParam);
254  Step<Real>::getState()->searchSize = penaltyParam;
255  isPenaltyChanged_ = true;
256  modified = true;
257  }
258 
259  if( delta_ > deltaMin_ && !modified ) {
260  Real deltaNext = delta_ * deltaUpdate_;
261  if( gPhiNorm < deltaNext ) {
262  delta_ = deltaNext;
263  fletcher.setDelta(deltaNext);
264  isDeltaChanged_ = true;
265  modified = true;
266  }
267  }
268 
269  if( modified ) {
270  // Penalty function has been changed somehow, need to recompute
271  Real tol = static_cast<Real>(1e-12);
272  tr_algo_state_.value = fletcher.value(x, tol);
273  fletcher.gradient(*g_, x, tol);
274 
275  tr_algo_state_.nfval++;
276  tr_algo_state_.ngrad++;
277  tr_algo_state_.ncval++;
278  tr_algo_state_.minIter = tr_algo_state_.iter;
279  tr_algo_state_.minValue = tr_algo_state_.value;
280  tr_algo_state_.gnorm = computeProjGradientNorm(*g_, x, bnd);
281  }
282 
283  // Update the step and store in state
284  algo_state.iterateVec->set(x);
285  algo_state.iter++;
286 
287  fletcherState->descentVec->set(s);
288  fletcherState->gradientVec->set(*(fletcher.getLagrangianGradient(x)));
289  fletcherState->constraintVec->set(*(fletcher.getConstraintVec(x)));
290 
291  // Update objective function value
292  algo_state.value = fletcher.getObjectiveValue(x);
293  // Update constraint value
294  algo_state.cnorm = (fletcherState->constraintVec)->norm();
295  // Update the step size
296  algo_state.snorm = tr_algo_state_.snorm;
297  // Compute gradient of the Lagrangian
298  algo_state.gnorm = computeProjGradientNorm(*(fletcherState->gradientVec),
299  x, bnd);
300  // Compute gradient of penalty function
301  algo_state.aggregateGradientNorm = tr_algo_state_.gnorm;
302  // Update evaluation countersgetConstraintVec
303  algo_state.nfval = fletcher.getNumberFunctionEvaluations();
304  algo_state.ngrad = fletcher.getNumberGradientEvaluations();
305  algo_state.ncval = fletcher.getNumberConstraintEvaluations();
306  // Update objective function and constraints
307  // fletcher.update(x,true,algo_state.iter);
308  // Update multipliers
309  algo_state.lagmultVec->set(*(fletcher.getMultiplierVec(x)));
310  }
311 
314  std::string printHeader( void ) const {
315  std::stringstream hist;
316  if( subStep_ == "Trust Region" ) {
317  hist << " ";
318  hist << std::setw(6) << std::left << "iter";
319  hist << std::setw(15) << std::left << "merit";
320  hist << std::setw(15) << std::left << "fval";
321  hist << std::setw(15) << std::left << "gpnorm";
322  hist << std::setw(15) << std::left << "gLnorm";
323  hist << std::setw(15) << std::left << "cnorm";
324  hist << std::setw(15) << std::left << "snorm";
325  hist << std::setw(15) << std::left << "tr_radius";
326  hist << std::setw(10) << std::left << "tr_flag";
327  if ( etr_ == TRUSTREGION_TRUNCATEDCG && subStep_ == "Trust Region") {
328  hist << std::setw(10) << std::left << "iterCG";
329  hist << std::setw(10) << std::left << "flagCG";
330  }
331  hist << std::setw(15) << std::left << "penalty";
332  hist << std::setw(15) << std::left << "delta";
333  hist << std::setw(10) << std::left << "#fval";
334  hist << std::setw(10) << std::left << "#grad";
335  hist << std::setw(10) << std::left << "#cval";
336  hist << "\n";
337  }
338  else {
339  std::string stepHeader = step_->printHeader();
340  stepHeaderLength_ = stepHeader.length();
341  hist << stepHeader.substr(0, stepHeaderLength_-1);
342  hist << std::setw(15) << std::left << "fval";
343  hist << std::setw(15) << std::left << "gLnorm";
344  hist << std::setw(15) << std::left << "cnorm";
345  hist << std::setw(15) << std::left << "penalty";
346  hist << std::setw(15) << std::left << "delta";
347  hist << std::setw(10) << std::left << "#cval";
348  hist << "\n";
349  }
350  return hist.str();
351  }
352 
355  std::string printName( void ) const {
356  std::stringstream hist;
357  hist << "\n" << " Fletcher solver : " << subStep_;
358  hist << "\n";
359  return hist.str();
360  }
361 
364  std::string print( AlgorithmState<Real> &algo_state, bool pHeader = false ) const {
365  std::string stepHist = step_->print( tr_algo_state_, false );
366  stepHist.erase(std::remove(stepHist.end()-3, stepHist.end(),'\n'), stepHist.end());
367  std::string name = step_->printName();
368  size_t pos = stepHist.find(name);
369  if ( pos != std::string::npos ) {
370  stepHist.erase(pos, name.length());
371  }
372 
373  std::stringstream hist;
374  hist << std::scientific << std::setprecision(6);
375  if ( algo_state.iter == 0 ) {
376  hist << printName();
377  }
378  if ( pHeader ) {
379  hist << printHeader();
380  }
381 
382  std::string penaltyString = getValueString( Step<Real>::getStepState()->searchSize, isPenaltyChanged_ );
383  std::string deltaString = getValueString( delta_, isDeltaChanged_ );
384 
385  if( subStep_ == "Trust Region" ) {
386  hist << " ";
387  hist << std::setw(6) << std::left << algo_state.iter;
388  hist << std::setw(15) << std::left << tr_algo_state_.value;
389  hist << std::setw(15) << std::left << algo_state.value;
390  hist << std::setw(15) << std::left << tr_algo_state_.gnorm;
391  hist << std::setw(15) << std::left << algo_state.gnorm;
392  hist << std::setw(15) << std::left << algo_state.cnorm;
393  hist << std::setw(15) << std::left << stepHist.substr(38,15); // snorm
394  hist << std::setw(15) << std::left << stepHist.substr(53,15); // tr_radius
395  hist << std::setw(10) << std::left << (algo_state.iter == 0 ? "" : stepHist.substr(88,10)); // tr_flag
396  if ( etr_ == TRUSTREGION_TRUNCATEDCG && subStep_ == "Trust Region") {
397  hist << std::setw(10) << std::left << (algo_state.iter == 0 ? "" : stepHist.substr(93,10)); // iterCG
398  hist << std::setw(10) << std::left << (algo_state.iter == 0 ? "" : stepHist.substr(103,10)); // flagCG
399  }
400  hist << std::setw(15) << std::left << penaltyString;
401  hist << std::setw(15) << std::left << deltaString;
402  hist << std::setw(10) << std::left << (algo_state.iter == 0 ? "" : stepHist.substr(68,10)); // #fval
403  hist << std::setw(10) << std::left << (algo_state.iter == 0 ? "" : stepHist.substr(78,10)); // #gval
404  hist << std::setw(10) << std::left << algo_state.ncval;
405  hist << "\n";
406  } else {
407  hist << std::setw(stepHeaderLength_-1) << std::left << stepHist;
408  hist << std::setw(15) << std::left << algo_state.value;
409  hist << std::setw(15) << std::left << algo_state.gnorm;
410  hist << std::setw(15) << std::left << algo_state.cnorm;
411  hist << std::setw(15) << std::left << penaltyString;
412  hist << std::setw(15) << std::left << deltaString;
413  hist << std::setw(10) << std::left << algo_state.ncval;
414  hist << "\n";
415  }
416 
417  return hist.str();
418  }
419 
420  std::string getValueString( const Real value, const bool print ) const {
421  std::stringstream valString;
422  valString << std::scientific << std::setprecision(6);
423  if( print ) {
424  valString << std::setw(15) << std::left << value;
425  } else {
426  valString << std::setw(15) << "";
427  }
428  return valString.str();
429  }
430 
436  AlgorithmState<Real> &algo_state ) {}
437 
443  AlgorithmState<Real> &algo_state ) {}
444 
445 }; // class FletcherStep
446 
447 } // namespace ROL
448 
449 #endif
void update(Vector< Real > &x, Vector< Real > &l, const Vector< Real > &s, Objective< Real > &obj, Constraint< Real > &con, BoundConstraint< Real > &bnd, AlgorithmState< Real > &algo_state)
Update step, if successful (equality and bound constraints).
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:192
int getNumberGradientEvaluations() const
void setDelta(Real delta)
virtual ROL::Ptr< Vector > clone() const =0
Clone to make a new (uninitialized) vector.
AlgorithmState< Real > tr_algo_state_
Real getObjectiveValue(const Vector< Real > &x)
bool isActivated(void) const
Check if bounds are on.
virtual Real value(const Vector< Real > &x, Real &tol)=0
Compute value.
Provides the interface to compute optimization steps.
Definition: ROL_Step.hpp:34
std::string print(AlgorithmState< Real > &algo_state, bool pHeader=false) const
Print iterate status.
void compute(Vector< Real > &s, const Vector< Real > &x, const Vector< Real > &l, Objective< Real > &obj, Constraint< Real > &con, AlgorithmState< Real > &algo_state)
Compute step (equality constraint).
Contains definitions of custom data types in ROL.
const Ptr< Vector< Real > > getMultiplierVec(const Vector< Real > &x)
ROL::Objective_SimOpt value
int getNumberFunctionEvaluations() const
FletcherStep(ROL::ParameterList &parlist)
void update(Vector< Real > &x, Vector< Real > &l, const Vector< Real > &s, Objective< Real > &obj, Constraint< Real > &con, AlgorithmState< Real > &algo_state)
Update step, if successful (equality constraint).
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:46
ROL::Ptr< BoundConstraint< Real > > bnd_
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
State for algorithm class. Will be used for restarts.
Definition: ROL_Types.hpp:109
ROL::Ptr< Vector< Real > > x_
virtual void gradient(Vector< Real > &g, const Vector< Real > &x, Real &tol)
Compute gradient.
void compute(Vector< Real > &s, const Vector< Real > &x, const Vector< Real > &l, Objective< Real > &obj, Constraint< Real > &con, BoundConstraint< Real > &bnd, AlgorithmState< Real > &algo_state)
Compute step (equality and bound constraints).
void setPenaltyParameter(Real sigma)
ROL::Ptr< StepState< Real > > getState(void)
Definition: ROL_Step.hpp:39
const Ptr< Vector< Real > > getConstraintVec(const Vector< Real > &x)
ROL::ParameterList parlist_
Real computeProjGradientNorm(const Vector< Real > &g, const Vector< Real > &x, BoundConstraint< Real > &bnd)
ROL::Ptr< Vector< Real > > iterateVec
Definition: ROL_Types.hpp:123
ROL::Ptr< Vector< Real > > g_
Provides the interface to compute Fletcher steps.
virtual void project(Vector< Real > &x)
Project optimization variables onto the bounds.
std::string getValueString(const Real value, const bool print) const
void update(Vector< Real > &x, const Vector< Real > &s, Objective< Real > &obj, BoundConstraint< Real > &con, AlgorithmState< Real > &algo_state)
Update step, for bound constraints; here only to satisfy the interface requirements, does nothing, needs refactoring.
int getNumberConstraintEvaluations() const
std::string printName(void) const
Print step name.
Provides the interface to apply upper and lower bound constraints.
void initialize(Vector< Real > &x, const Vector< Real > &g, Vector< Real > &l, const Vector< Real > &c, Objective< Real > &obj, Constraint< Real > &con, BoundConstraint< Real > &bnd, AlgorithmState< Real > &algo_state)
Initialize step with equality and bound constraints.
const Ptr< Vector< Real > > getLagrangianGradient(const Vector< Real > &x)
std::string printHeader(void) const
Print iterate header.
ETrustRegion StringToETrustRegion(std::string s)
ROL::Ptr< Vector< Real > > lagmultVec
Definition: ROL_Types.hpp:124
void compute(Vector< Real > &s, const Vector< Real > &x, Objective< Real > &obj, BoundConstraint< Real > &con, AlgorithmState< Real > &algo_state)
Compute step for bound constraints; here only to satisfy the interface requirements, does nothing, needs refactoring.
virtual Real norm() const =0
Returns where .
ETrustRegion
Enumeration of trust-region solver types.
void initialize(Vector< Real > &x, const Vector< Real > &g, Vector< Real > &l, const Vector< Real > &c, Objective< Real > &obj, Constraint< Real > &con, AlgorithmState< Real > &algo_state)
Initialize step with equality constraint.
ROL::Ptr< Step< Real > > step_
Defines the general constraint operator interface.
const ROL::Ptr< const StepState< Real > > getStepState(void) const
Get state for step object.
Definition: ROL_Step.hpp:177