ROL
ROL_FletcherStep.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_FLETCHERSTEP_H
45 #define ROL_FLETCHERSTEP_H
46 
47 #include "ROL_FletcherBase.hpp"
48 #include "ROL_Step.hpp"
49 #include "ROL_TrustRegionStep.hpp"
50 #include "ROL_LineSearchStep.hpp"
51 #include "ROL_Types.hpp"
52 #include "ROL_ParameterList.hpp"
53 
60 namespace ROL {
61 
62 template <class Real>
63 class FletcherStep : public Step<Real> {
64 private:
65  ROL::Ptr<Step<Real> > step_;
66  ROL::Ptr<BoundConstraint<Real> > bnd_;
67 
68  ROL::ParameterList parlist_;
69 
70  ROL::Ptr<Vector<Real> > x_;
71 
72  // Lagrange multiplier update
77  // Subproblem information
78  bool print_;
79  std::string subStep_;
80 
81  Real delta_;
82  Real deltaMin_;
85 
87 
88  ROL::Ptr<Vector<Real> > g_;
89 
91 
92  // For printing output
93  mutable bool isDeltaChanged_;
94  mutable bool isPenaltyChanged_;
95 
97 
98  mutable int stepHeaderLength_; // For formatting
99 
101  BoundConstraint<Real> &bnd) {
102  Real gnorm = 0.;
103  // Compute norm of projected gradient
104  if (bnd.isActivated()) {
105  x_->set(x);
106  x_->axpy(-1.,g.dual());
107  bnd.project(*x_);
108  x_->axpy(-1.,x);
109  gnorm = x_->norm();
110  }
111  else {
112  gnorm = g.norm();
113  }
114  return gnorm;
115  }
116 
117 public:
118 
120  using Step<Real>::compute;
121  using Step<Real>::update;
122 
124 
125  FletcherStep(ROL::ParameterList &parlist)
126  : Step<Real>(), bnd_activated_(false), numSuccessSteps_(0),
128  Real zero(0), one(1), two(2), oe8(1.e8), oe1(1.e-1), oem6(1e-6), oem8(1.e-8);
129 
130  ROL::ParameterList& sublist = parlist.sublist("Step").sublist("Fletcher");
131  Step<Real>::getState()->searchSize = sublist.get("Penalty Parameter",one);
132  delta_ = sublist.get("Regularization Parameter",zero);
133  deltaMin_ = sublist.get("Min Regularization Parameter",oem8);
134  deltaUpdate_ = sublist.get("Regularization Parameter Decrease Factor", oe1);
135  // penalty parameters
136  penaltyUpdate_ = sublist.get("Penalty Parameter Growth Factor", two);
137  modifyPenalty_ = sublist.get("Modify Penalty Parameter", false);
138  maxPenaltyParam_ = sublist.get("Maximum Penalty Parameter", oe8);
139  minPenaltyParam_ = sublist.get("Minimum Penalty Parameter", oem6);
140 
141  subStep_ = sublist.get("Subproblem Solver", "Trust Region");
142 
143  parlist_ = parlist;
144  }
145 
150  AlgorithmState<Real> &algo_state ) {
151  bnd_ = ROL::makePtr<BoundConstraint<Real>>();
152  bnd_->deactivate();
153  initialize(x,g,l,c,obj,con,*bnd_,algo_state);
154  }
155 
160  AlgorithmState<Real> &algo_state ) {
161  // Determine what kind of step
162  bnd_activated_ = bnd.isActivated();
163 
164  ROL::ParameterList trlist(parlist_);
165  bool inexactFletcher = trlist.sublist("Step").sublist("Fletcher").get("Inexact Solves", false);
166  if( inexactFletcher ) {
167  trlist.sublist("General").set("Inexact Objective Value", true);
168  trlist.sublist("General").set("Inexact Gradient", true);
169  }
170  if( bnd_activated_ ) {
171  trlist.sublist("Step").sublist("Trust Region").set("Subproblem Model", "Coleman-Li");
172  }
173 
174  if ( subStep_ == "Line Search" ) {
175  step_ = makePtr<LineSearchStep<Real>>(trlist);
176  }
177  else {
178  step_ = makePtr<TrustRegionStep<Real>>(trlist);
179  }
180  etr_ = StringToETrustRegion(parlist_.sublist("Step").sublist("Trust Region").get("Subproblem Solver", "Truncated CG"));
181 
182  // Initialize class members
183  g_ = g.clone();
184  x_ = x.clone();
185 
186  // Rest of initialize
187  FletcherBase<Real>& fletcher = dynamic_cast<FletcherBase<Real>&>(obj);
188 
189  tr_algo_state_.iterateVec = x.clone();
190  tr_algo_state_.minIterVec = x.clone();
191  tr_algo_state_.lagmultVec = l.clone();
192 
193  step_->initialize(x, g, obj, bnd, tr_algo_state_);
194 
195  // Initialize step state
196  ROL::Ptr<StepState<Real> > state = Step<Real>::getState();
197  state->descentVec = x.clone();
198  state->gradientVec = g.clone();
199  state->constraintVec = c.clone();
200  // Initialize the algorithm state
201  algo_state.nfval = 0;
202  algo_state.ncval = 0;
203  algo_state.ngrad = 0;
204 
205  algo_state.value = fletcher.getObjectiveValue(x);
206  algo_state.gnorm = computeProjGradientNorm(*(fletcher.getLagrangianGradient(x)),
207  x, bnd);
208  algo_state.aggregateGradientNorm = tr_algo_state_.gnorm;
209 
210  state->constraintVec->set(*(fletcher.getConstraintVec(x)));
211  algo_state.cnorm = (state->constraintVec)->norm();
212  // Update evaluation counters
213  algo_state.ncval = fletcher.getNumberConstraintEvaluations();
214  algo_state.nfval = fletcher.getNumberFunctionEvaluations();
215  algo_state.ngrad = fletcher.getNumberGradientEvaluations();
216  }
217 
220  void compute( Vector<Real> &s, const Vector<Real> &x, const Vector<Real> &l,
221  Objective<Real> &obj, Constraint<Real> &con,
222  AlgorithmState<Real> &algo_state ) {
223  compute(s,x,l,obj,con,*bnd_, algo_state);
224  }
225 
228  void compute( Vector<Real> &s, const Vector<Real> &x, const Vector<Real> &l,
229  Objective<Real> &obj, Constraint<Real> &con,
230  BoundConstraint<Real> &bnd, AlgorithmState<Real> &algo_state ) {
231  step_->compute( s, x, obj, bnd, tr_algo_state_ );
232  }
233 
238  AlgorithmState<Real> &algo_state ) {
239  update(x,l,s,obj,con,*bnd_, algo_state);
240  }
241 
247  AlgorithmState<Real> &algo_state ) {
248 
249  // This should be in print, but this will not work there
250  isDeltaChanged_ = false;
251  isPenaltyChanged_ = false;
252  bool modified = false;
253 
254  FletcherBase<Real> &fletcher = dynamic_cast<FletcherBase<Real>&>(obj);
255  ROL::Ptr<StepState<Real> > fletcherState = Step<Real>::getState();
256  const ROL::Ptr<const StepState<Real> > state = step_->getStepState();
257 
258  step_->update(x,s,obj,bnd,tr_algo_state_);
259  numSuccessSteps_ += (state->flag == 0);
260 
261  Real gPhiNorm = tr_algo_state_.gnorm;
262  Real cnorm = (fletcherState->constraintVec)->norm();
263  bool too_infeasible = cnorm > static_cast<Real>(100.)*gPhiNorm;
264  bool too_feasible = cnorm < static_cast<Real>(1e-2)*gPhiNorm;
265 
266  if( too_infeasible && !modified && modifyPenalty_ && numSuccessSteps_ > 1 ) {
267  Real penaltyParam = Step<Real>::getStepState()->searchSize;
268  if( penaltyParam >= maxPenaltyParam_ ) {
269  // Penalty parameter too large, exit
270  algo_state.flag = true;
271  }
272  penaltyParam *= penaltyUpdate_;
273  penaltyParam = std::min(penaltyParam, maxPenaltyParam_);
274  fletcher.setPenaltyParameter(penaltyParam);
275  Step<Real>::getState()->searchSize = penaltyParam;
276  isPenaltyChanged_ = true;
277  modified = true;
278  }
279 
280  if( too_feasible && !modified && modifyPenalty_ && numSuccessSteps_ > 1 ) {
281  Real penaltyParam = Step<Real>::getStepState()->searchSize;
282  if( penaltyParam <= minPenaltyParam_ ) {
283  // Penalty parameter too small, exit (this is unlikely)
284  algo_state.flag = true;
285  }
286  penaltyParam /= penaltyUpdate_;
287  penaltyParam = std::max(penaltyParam, minPenaltyParam_);
288  fletcher.setPenaltyParameter(penaltyParam);
289  Step<Real>::getState()->searchSize = penaltyParam;
290  isPenaltyChanged_ = true;
291  modified = true;
292  }
293 
294  if( delta_ > deltaMin_ && !modified ) {
295  Real deltaNext = delta_ * deltaUpdate_;
296  if( gPhiNorm < deltaNext ) {
297  delta_ = deltaNext;
298  fletcher.setDelta(deltaNext);
299  isDeltaChanged_ = true;
300  modified = true;
301  }
302  }
303 
304  if( modified ) {
305  // Penalty function has been changed somehow, need to recompute
306  Real tol = static_cast<Real>(1e-12);
307  tr_algo_state_.value = fletcher.value(x, tol);
308  fletcher.gradient(*g_, x, tol);
309 
310  tr_algo_state_.nfval++;
311  tr_algo_state_.ngrad++;
312  tr_algo_state_.ncval++;
313  tr_algo_state_.minIter = tr_algo_state_.iter;
314  tr_algo_state_.minValue = tr_algo_state_.value;
315  tr_algo_state_.gnorm = computeProjGradientNorm(*g_, x, bnd);
316  }
317 
318  // Update the step and store in state
319  algo_state.iterateVec->set(x);
320  algo_state.iter++;
321 
322  fletcherState->descentVec->set(s);
323  fletcherState->gradientVec->set(*(fletcher.getLagrangianGradient(x)));
324  fletcherState->constraintVec->set(*(fletcher.getConstraintVec(x)));
325 
326  // Update objective function value
327  algo_state.value = fletcher.getObjectiveValue(x);
328  // Update constraint value
329  algo_state.cnorm = (fletcherState->constraintVec)->norm();
330  // Update the step size
331  algo_state.snorm = tr_algo_state_.snorm;
332  // Compute gradient of the Lagrangian
333  algo_state.gnorm = computeProjGradientNorm(*(fletcherState->gradientVec),
334  x, bnd);
335  // Compute gradient of penalty function
336  algo_state.aggregateGradientNorm = tr_algo_state_.gnorm;
337  // Update evaluation countersgetConstraintVec
338  algo_state.nfval = fletcher.getNumberFunctionEvaluations();
339  algo_state.ngrad = fletcher.getNumberGradientEvaluations();
340  algo_state.ncval = fletcher.getNumberConstraintEvaluations();
341  // Update objective function and constraints
342  // fletcher.update(x,true,algo_state.iter);
343  // bnd.update(x,true,algo_state.iter);
344  // Update multipliers
345  algo_state.lagmultVec->set(*(fletcher.getMultiplierVec(x)));
346  }
347 
350  std::string printHeader( void ) const {
351  std::stringstream hist;
352  if( subStep_ == "Trust Region" ) {
353  hist << " ";
354  hist << std::setw(6) << std::left << "iter";
355  hist << std::setw(15) << std::left << "merit";
356  hist << std::setw(15) << std::left << "fval";
357  hist << std::setw(15) << std::left << "gpnorm";
358  hist << std::setw(15) << std::left << "gLnorm";
359  hist << std::setw(15) << std::left << "cnorm";
360  hist << std::setw(15) << std::left << "snorm";
361  hist << std::setw(15) << std::left << "tr_radius";
362  hist << std::setw(10) << std::left << "tr_flag";
363  if ( etr_ == TRUSTREGION_TRUNCATEDCG && subStep_ == "Trust Region") {
364  hist << std::setw(10) << std::left << "iterCG";
365  hist << std::setw(10) << std::left << "flagCG";
366  }
367  hist << std::setw(15) << std::left << "penalty";
368  hist << std::setw(15) << std::left << "delta";
369  hist << std::setw(10) << std::left << "#fval";
370  hist << std::setw(10) << std::left << "#grad";
371  hist << std::setw(10) << std::left << "#cval";
372  hist << "\n";
373  }
374  else {
375  std::string stepHeader = step_->printHeader();
376  stepHeaderLength_ = stepHeader.length();
377  hist << stepHeader.substr(0, stepHeaderLength_-1);
378  hist << std::setw(15) << std::left << "fval";
379  hist << std::setw(15) << std::left << "gLnorm";
380  hist << std::setw(15) << std::left << "cnorm";
381  hist << std::setw(15) << std::left << "penalty";
382  hist << std::setw(15) << std::left << "delta";
383  hist << std::setw(10) << std::left << "#cval";
384  hist << "\n";
385  }
386  return hist.str();
387  }
388 
391  std::string printName( void ) const {
392  std::stringstream hist;
393  hist << "\n" << " Fletcher solver : " << subStep_;
394  hist << "\n";
395  return hist.str();
396  }
397 
400  std::string print( AlgorithmState<Real> &algo_state, bool pHeader = false ) const {
401  std::string stepHist = step_->print( tr_algo_state_, false );
402  stepHist.erase(std::remove(stepHist.end()-3, stepHist.end(),'\n'), stepHist.end());
403  std::string name = step_->printName();
404  size_t pos = stepHist.find(name);
405  if ( pos != std::string::npos ) {
406  stepHist.erase(pos, name.length());
407  }
408 
409  std::stringstream hist;
410  hist << std::scientific << std::setprecision(6);
411  if ( algo_state.iter == 0 ) {
412  hist << printName();
413  }
414  if ( pHeader ) {
415  hist << printHeader();
416  }
417 
418  std::string penaltyString = getValueString( Step<Real>::getStepState()->searchSize, isPenaltyChanged_ );
419  std::string deltaString = getValueString( delta_, isDeltaChanged_ );
420 
421  if( subStep_ == "Trust Region" ) {
422  hist << " ";
423  hist << std::setw(6) << std::left << algo_state.iter;
424  hist << std::setw(15) << std::left << tr_algo_state_.value;
425  hist << std::setw(15) << std::left << algo_state.value;
426  hist << std::setw(15) << std::left << tr_algo_state_.gnorm;
427  hist << std::setw(15) << std::left << algo_state.gnorm;
428  hist << std::setw(15) << std::left << algo_state.cnorm;
429  hist << std::setw(15) << std::left << stepHist.substr(38,15); // snorm
430  hist << std::setw(15) << std::left << stepHist.substr(53,15); // tr_radius
431  hist << std::setw(10) << std::left << (algo_state.iter == 0 ? "" : stepHist.substr(88,10)); // tr_flag
432  if ( etr_ == TRUSTREGION_TRUNCATEDCG && subStep_ == "Trust Region") {
433  hist << std::setw(10) << std::left << (algo_state.iter == 0 ? "" : stepHist.substr(93,10)); // iterCG
434  hist << std::setw(10) << std::left << (algo_state.iter == 0 ? "" : stepHist.substr(103,10)); // flagCG
435  }
436  hist << std::setw(15) << std::left << penaltyString;
437  hist << std::setw(15) << std::left << deltaString;
438  hist << std::setw(10) << std::left << (algo_state.iter == 0 ? "" : stepHist.substr(68,10)); // #fval
439  hist << std::setw(10) << std::left << (algo_state.iter == 0 ? "" : stepHist.substr(78,10)); // #gval
440  hist << std::setw(10) << std::left << algo_state.ncval;
441  hist << "\n";
442  } else {
443  hist << std::setw(stepHeaderLength_-1) << std::left << stepHist;
444  hist << std::setw(15) << std::left << algo_state.value;
445  hist << std::setw(15) << std::left << algo_state.gnorm;
446  hist << std::setw(15) << std::left << algo_state.cnorm;
447  hist << std::setw(15) << std::left << penaltyString;
448  hist << std::setw(15) << std::left << deltaString;
449  hist << std::setw(10) << std::left << algo_state.ncval;
450  hist << "\n";
451  }
452 
453  return hist.str();
454  }
455 
456  std::string getValueString( const Real value, const bool print ) const {
457  std::stringstream valString;
458  valString << std::scientific << std::setprecision(6);
459  if( print ) {
460  valString << std::setw(15) << std::left << value;
461  } else {
462  valString << std::setw(15) << "";
463  }
464  return valString.str();
465  }
466 
472  AlgorithmState<Real> &algo_state ) {}
473 
479  AlgorithmState<Real> &algo_state ) {}
480 
481 }; // class FletcherStep
482 
483 } // namespace ROL
484 
485 #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:226
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:69
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:80
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:143
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:74
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:157
ROL::Ptr< Vector< Real > > g_
Provides the interface to compute Fletcher steps.
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:158
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.
virtual void project(Vector< Real > &x)
Project optimization variables onto the bounds.
const ROL::Ptr< const StepState< Real > > getStepState(void) const
Get state for step object.
Definition: ROL_Step.hpp:293