ROL
ROL_TypeE_StabilizedLCLAlgorithm_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_TYPEE_STABILIZEDLCLALGORITHM_DEF_H
11 #define ROL_TYPEE_STABILIZEDLCLALGORITHM_DEF_H
12 
14 #include "ROL_Bounds.hpp"
15 
16 namespace ROL {
17 namespace TypeE {
18 
19 template<typename Real>
20 StabilizedLCLAlgorithm<Real>::StabilizedLCLAlgorithm( ParameterList &list, const Ptr<Secant<Real>> &secant )
21  : TypeE::Algorithm<Real>::Algorithm(), secant_(secant), list_(list), subproblemIter_(0) {
22  // Set status test
23  status_->reset();
24  status_->add(makePtr<ConstraintStatusTest<Real>>(list));
25 
26  Real one(1), p1(0.1), p9(0.9), ten(1.e1), oe8(1.e8), oem8(1.e-8);
27  ParameterList& sublist = list.sublist("Step").sublist("Stabilized LCL");
28  useDefaultInitPen_ = sublist.get("Use Default Initial Penalty Parameter", true);
29  state_->searchSize = sublist.get("Initial Penalty Parameter", ten);
30  sigma_ = sublist.get("Initial Elastic Penalty Parameter", ten*ten);
31  // Multiplier update parameters
32  scaleLagrangian_ = sublist.get("Use Scaled Stabilized LCL", false);
33  penaltyUpdate_ = sublist.get("Penalty Parameter Growth Factor", ten);
34  maxPenaltyParam_ = sublist.get("Maximum Penalty Parameter", oe8);
35  sigmaMax_ = sublist.get("Maximum Elastic Penalty Parameter", oe8);
36  sigmaUpdate_ = sublist.get("Elastic Penalty Parameter Growth Rate", ten);
37  // Optimality tolerance update
38  optIncreaseExponent_ = sublist.get("Optimality Tolerance Increase Exponent", one);
39  optDecreaseExponent_ = sublist.get("Optimality Tolerance Decrease Exponent", one);
40  optToleranceInitial_ = sublist.get("Initial Optimality Tolerance", one);
41  // Feasibility tolerance update
42  feasIncreaseExponent_ = sublist.get("Feasibility Tolerance Increase Exponent", p9);
43  feasDecreaseExponent_ = sublist.get("Feasibility Tolerance Decrease Exponent", p1);
44  feasToleranceInitial_ = sublist.get("Initial Feasibility Tolerance", one);
45  // Subproblem information
46  maxit_ = sublist.get("Subproblem Iteration Limit", 1000);
47  subStep_ = sublist.get("Subproblem Step Type", "Trust Region");
48  HessianApprox_ = sublist.get("Level of Hessian Approximation", 0);
49  list_.sublist("Step").set("Type",subStep_);
50  list_.sublist("Status Test").set("Iteration Limit",maxit_);
51  // Verbosity setting
52  verbosity_ = list.sublist("General").get("Output Level", 0);
54  bool print = verbosity_ > 2;
55  list_.sublist("General").set("Output Level",(print ? verbosity_ : 0));
56  // Outer iteration tolerances
57  outerFeasTolerance_ = list.sublist("Status Test").get("Constraint Tolerance", oem8);
58  outerOptTolerance_ = list.sublist("Status Test").get("Gradient Tolerance", oem8);
59  outerStepTolerance_ = list.sublist("Status Test").get("Step Tolerance", oem8);
60  // Scaling
61  useDefaultScaling_ = sublist.get("Use Default Problem Scaling", true);
62  fscale_ = sublist.get("Objective Scaling", one);
63  cscale_ = sublist.get("Constraint Scaling", one);
64 }
65 
66 template<typename Real>
68  const Vector<Real> &g,
69  const Vector<Real> &l,
70  const Vector<Real> &c,
72  Constraint<Real> &con,
73  std::ostream &outStream ) {
74  const Real one(1), TOL(1.e-2);
75  Real tol = std::sqrt(ROL_EPSILON<Real>());
77 
78  // Initialize the algorithm state
79  state_->nfval = 0;
80  state_->ncval = 0;
81  state_->ngrad = 0;
82 
83  // Compute objective value
84  alobj.getAugmentedLagrangian()->update(x,UpdateType::Initial,state_->iter);
85  state_->value = alobj.getObjectiveValue(x,tol);
86  alobj.getAugmentedLagrangian()->gradient(*state_->gradientVec,x,tol);
87 
88  // Compute constraint violation
89  state_->constraintVec->set(*alobj.getConstraintVec(x,tol));
90  state_->cnorm = state_->constraintVec->norm();
91 
92  // Update evaluation counters
93  state_->ncval += alobj.getNumberConstraintEvaluations();
94  state_->nfval += alobj.getNumberFunctionEvaluations();
95  state_->ngrad += alobj.getNumberGradientEvaluations();
96 
97  // Compute problem scaling
98  if (useDefaultScaling_) {
99  fscale_ = one/std::max(one,alobj.getObjectiveGradient(x,tol)->norm());
100  try {
101  Ptr<Vector<Real>> ji = x.clone();
102  Real maxji(0), normji(0);
103  for (int i = 0; i < c.dimension(); ++i) {
104  con.applyAdjointJacobian(*ji,*c.basis(i),x,tol);
105  normji = ji->norm();
106  maxji = std::max(normji,maxji);
107  }
108  cscale_ = one/std::max(one,maxji);
109  }
110  catch (std::exception &e) {
111  cscale_ = one;
112  }
113  }
114  alobj.setScaling(fscale_,cscale_);
115 
116  // Compute gradient of the lagrangian
117  state_->gnorm = state_->gradientVec->norm()/std::min(fscale_,cscale_);
118 
119  // Compute initial penalty parameter
120  if (useDefaultInitPen_) {
121  const Real oem8(1e-8), oem2(1e-2), two(2), ten(10);
122  state_->searchSize = std::max(oem8,
123  std::min(ten*std::max(one,std::abs(fscale_*state_->value))
124  / std::max(one,std::pow(cscale_*state_->cnorm,two)),oem2*maxPenaltyParam_));
125  }
126  // Initialize intermediate stopping tolerances
127  optTolerance_ = std::max<Real>(TOL*outerOptTolerance_,
128  optToleranceInitial_);
129  //optTolerance_ = std::min<Real>(optTolerance_,TOL*state_->gnorm);
130  feasTolerance_ = std::max<Real>(TOL*outerFeasTolerance_,
131  feasToleranceInitial_);
132 
133  // Set data
134  alobj.reset(l,state_->searchSize,sigma_);
135 
136  if (verbosity_ > 1) {
137  outStream << std::endl;
138  outStream << "Stabilized LCL Initialize" << std::endl;
139  outStream << "Objective Scaling: " << fscale_ << std::endl;
140  outStream << "Constraint Scaling: " << cscale_ << std::endl;
141  outStream << "Penalty Parameter: " << state_->searchSize << std::endl;
142  outStream << std::endl;
143  }
144 }
145 
146 template<typename Real>
148  std::ostream &outStream ) {
149  if (problem.getProblemType() == TYPE_E) {
150  problem.edit();
151  problem.finalize(true,verbosity_>3,outStream); // Lump linear and nonlinear constraints
152  run(*problem.getPrimalOptimizationVector(),
153  *problem.getDualOptimizationVector(),
154  *problem.getObjective(),
155  *problem.getConstraint(),
156  *problem.getMultiplierVector(),
157  *problem.getResidualVector(),
158  outStream);
159  problem.finalizeIteration();
160  }
161  else {
162  throw Exception::NotImplemented(">>> ROL::TypeE::Algorithm::run : Optimization problem is not Type E!");
163  }
164 }
165 
166 template<typename Real>
168  const Vector<Real> &g,
169  Objective<Real> &obj,
170  Constraint<Real> &econ,
171  Vector<Real> &emul,
172  const Vector<Real> &eres,
173  std::ostream &outStream ) {
174  const Real one(1), oem2(1e-2);
175  Real tol(std::sqrt(ROL_EPSILON<Real>())), cnorm(0), lnorm;;
176  // Initialize augmented Lagrangian data
177  ElasticObjective<Real> alobj(makePtrFromRef(obj),makePtrFromRef(econ),
178  state_->searchSize,sigma_,g,eres,emul,
179  scaleLagrangian_,HessianApprox_);
180  initialize(x,g,emul,eres,alobj,econ,outStream);
181  // Define Elastic Subproblem
182  Ptr<Vector<Real>> u = eres.clone(), v = eres.clone(), c = eres.clone();
183  Ptr<Vector<Real>> gu = emul.clone(), gv = emul.clone(), l = emul.clone();
184  Ptr<Vector<Real>> s = x.clone(), gs = g.clone(), cvec = eres.clone();
185  Ptr<ElasticLinearConstraint<Real>> lcon
186  = makePtr<ElasticLinearConstraint<Real>>(makePtrFromRef(x),
187  makePtrFromRef(econ),
188  makePtrFromRef(eres));
189  std::vector<Ptr<Vector<Real>>> vecList = {s,u,v};
190  Ptr<PartitionedVector<Real>> xp = makePtr<PartitionedVector<Real>>(vecList);
191  Ptr<PartitionedVector<Real>> gxp = makePtr<PartitionedVector<Real>>({gs,gu,gv});
192  Ptr<Vector<Real>> lb = u->clone(); lb->zero();
193  std::vector<Ptr<BoundConstraint<Real>>> bndList(3);
194  bndList[0] = makePtr<BoundConstraint<Real>>(); bndList[0]->deactivate();
195  bndList[1] = makePtr<Bounds<Real>>(*lb,true);
196  bndList[2] = makePtr<Bounds<Real>>(*lb,true);
197  Ptr<BoundConstraint<Real>> xbnd
198  = makePtr<BoundConstraint_Partitioned<Real>>(bndList,vecList);
199  ParameterList ppa_list;
200  if (c->dimension() == 1)
201  ppa_list.sublist("General").sublist("Polyhedral Projection").set("Type","Dai-Fletcher");
202  else
203  ppa_list.sublist("General").sublist("Polyhedral Projection").set("Type","Semismooth Newton");
204  Problem<Real> elc(makePtrFromRef(alobj),xp,gxp);
205  elc.addBoundConstraint(xbnd);
206  elc.addLinearConstraint("ElasticLinearConstraint",lcon,l,c);
207  elc.finalize(false,verbosity_>2,outStream);
208  Ptr<Vector<Real>> b2 = eres.clone(), xpwa = xp->clone(), mul = emul.clone();
209  b2->zero();
210 
211  // Initialize subproblem algorithm
212  Ptr<TypeB::Algorithm<Real>> algo;
213 
214  // Output
215  if (verbosity_ > 0) writeOutput(outStream,true);
216 
217  while (status_->check(*state_)) {
218  lcon->setAnchor(state_->iterateVec);
219  if (verbosity_ > 3) elc.check(true,outStream);
220 
221  // Solve linearly constrained augmented Lagrangian subproblem
222  list_.sublist("Status Test").set("Gradient Tolerance",optTolerance_);
223  list_.sublist("Status Test").set("Step Tolerance",1.e-6*optTolerance_);
224  algo = TypeB::AlgorithmFactory<Real>(list_,secant_);
225  algo->run(elc,outStream);
226  x.set(*xp->get(0));
227 
228  // Update evaluation counters
229  subproblemIter_ = algo->getState()->iter;
230  state_->nfval += alobj.getNumberFunctionEvaluations();
231  state_->ngrad += alobj.getNumberGradientEvaluations();
232  state_->ncval += alobj.getNumberConstraintEvaluations();
233 
234  // Compute step
235  state_->stepVec->set(x);
236  state_->stepVec->axpy(-one,*state_->iterateVec);
237  state_->snorm = state_->stepVec->norm();
238 
239  // Update iteration information
240  state_->iter++;
241  cvec->set(*alobj.getConstraintVec(x,tol));
242  cnorm = cvec->norm();
243  if ( cscale_*cnorm < feasTolerance_ ) {
244  // Update iteration information
245  state_->iterateVec->set(x);
246  state_->value = alobj.getObjectiveValue(x,tol);
247  state_->constraintVec->set(*cvec);
248  state_->cnorm = cnorm;
249 
250  // Update multipliers
251  emul.axpy(static_cast<Real>(-1),*elc.getPolyhedralProjection()->getMultiplier());
252  emul.axpy(state_->searchSize*cscale_,state_->constraintVec->dual());
253 
254  alobj.getAugmentedLagrangian()->gradient(*state_->gradientVec,x,tol);
255  if (scaleLagrangian_) state_->gradientVec->scale(state_->searchSize);
256  econ.applyAdjointJacobian(*gs,*elc.getPolyhedralProjection()->getMultiplier(),x,tol);
257  state_->gradientVec->axpy(-cscale_,*gs);
258  state_->gnorm = state_->gradientVec->norm();
259 
260  // Update subproblem information
261  lnorm = mul->norm();
262  sigma_ = std::min(one+lnorm,sigmaMax_)/(one+state_->searchSize);
263  if ( algo->getState()->statusFlag == EXITSTATUS_CONVERGED ) {
264  optTolerance_ = std::max(oem2*outerOptTolerance_,
265  optTolerance_/(one + std::pow(state_->searchSize,optIncreaseExponent_)));
266  }
267  feasTolerance_ = std::max(oem2*outerFeasTolerance_,
268  feasTolerance_/(one + std::pow(state_->searchSize,feasIncreaseExponent_)));
269 
270  // Update Algorithm State
271  state_->snorm += lnorm + state_->searchSize*cscale_*state_->cnorm;
272  state_->lagmultVec->set(emul);
273  }
274  else {
275  // Update subproblem information
276  state_->searchSize = std::min(penaltyUpdate_*state_->searchSize,maxPenaltyParam_);
277  sigma_ /= sigmaUpdate_;
278  optTolerance_ = std::max(oem2*outerOptTolerance_,
279  optToleranceInitial_/(one + std::pow(state_->searchSize,optDecreaseExponent_)));
280  feasTolerance_ = std::max(oem2*outerFeasTolerance_,
281  feasToleranceInitial_/(one + std::pow(state_->searchSize,feasDecreaseExponent_)));
282  }
283  alobj.reset(emul,state_->searchSize,sigma_);
284 
285  // Update Output
286  if (verbosity_ > 0) writeOutput(outStream,printHeader_);
287  }
288  if (verbosity_ > 0) TypeE::Algorithm<Real>::writeExitStatus(outStream);
289 }
290 
291 template<typename Real>
292 void StabilizedLCLAlgorithm<Real>::writeHeader( std::ostream& os ) const {
293  std::ios_base::fmtflags osFlags(os.flags());
294  if(verbosity_>1) {
295  os << std::string(114,'-') << std::endl;
296  os << "Stabilized LCL status output definitions" << std::endl << std::endl;
297  os << " iter - Number of iterates (steps taken)" << std::endl;
298  os << " fval - Objective function value" << std::endl;
299  os << " cnorm - Norm of the constraint violation" << std::endl;
300  os << " gLnorm - Norm of the gradient of the Lagrangian" << std::endl;
301  os << " snorm - Norm of the step" << std::endl;
302  os << " penalty - Penalty parameter" << std::endl;
303  os << " sigma - Elastic Penalty parameter" << std::endl;
304  os << " feasTol - Feasibility tolerance" << std::endl;
305  os << " optTol - Optimality tolerance" << std::endl;
306  os << " #fval - Number of times the objective was computed" << std::endl;
307  os << " #grad - Number of times the gradient was computed" << std::endl;
308  os << " #cval - Number of times the constraint was computed" << std::endl;
309  os << " subIter - Number of iterations to solve subproblem" << std::endl;
310  os << std::string(114,'-') << std::endl;
311  }
312  os << " ";
313  os << std::setw(6) << std::left << "iter";
314  os << std::setw(15) << std::left << "fval";
315  os << std::setw(15) << std::left << "cnorm";
316  os << std::setw(15) << std::left << "gLnorm";
317  os << std::setw(15) << std::left << "snorm";
318  os << std::setw(10) << std::left << "penalty";
319  os << std::setw(10) << std::left << "sigma";
320  os << std::setw(10) << std::left << "feasTol";
321  os << std::setw(10) << std::left << "optTol";
322  os << std::setw(8) << std::left << "#fval";
323  os << std::setw(8) << std::left << "#grad";
324  os << std::setw(8) << std::left << "#cval";
325  os << std::setw(8) << std::left << "subIter";
326  os << std::endl;
327  os.flags(osFlags);
328 }
329 
330 template<typename Real>
331 void StabilizedLCLAlgorithm<Real>::writeName( std::ostream& os ) const {
332  std::ios_base::fmtflags osFlags(os.flags());
333  os << std::endl << "Stabilized LCL Solver (Type E, Equality Constraints)";
334  os << std::endl;
335  os << "Subproblem Solver: " << subStep_ << std::endl;
336  os.flags(osFlags);
337 }
338 
339 template<typename Real>
340 void StabilizedLCLAlgorithm<Real>::writeOutput( std::ostream& os, const bool print_header ) const {
341  std::ios_base::fmtflags osFlags(os.flags());
342  os << std::scientific << std::setprecision(6);
343  if ( state_->iter == 0 ) writeName(os);
344  if ( print_header ) writeHeader(os);
345  if ( state_->iter == 0 ) {
346  os << " ";
347  os << std::setw(6) << std::left << state_->iter;
348  os << std::setw(15) << std::left << state_->value;
349  os << std::setw(15) << std::left << state_->cnorm;
350  os << std::setw(15) << std::left << state_->gnorm;
351  os << std::setw(15) << std::left << "---";
352  os << std::scientific << std::setprecision(2);
353  os << std::setw(10) << std::left << state_->searchSize;
354  os << std::setw(10) << std::left << sigma_;
355  os << std::setw(10) << std::left << std::max(feasTolerance_,outerFeasTolerance_);
356  os << std::setw(10) << std::left << std::max(optTolerance_,outerOptTolerance_);
357  os << std::scientific << std::setprecision(6);
358  os << std::setw(8) << std::left << state_->nfval;
359  os << std::setw(8) << std::left << state_->ngrad;
360  os << std::setw(8) << std::left << state_->ncval;
361  os << std::setw(8) << std::left << "---";
362  os << std::endl;
363  }
364  else {
365  os << " ";
366  os << std::setw(6) << std::left << state_->iter;
367  os << std::setw(15) << std::left << state_->value;
368  os << std::setw(15) << std::left << state_->cnorm;
369  os << std::setw(15) << std::left << state_->gnorm;
370  os << std::setw(15) << std::left << state_->snorm;
371  os << std::scientific << std::setprecision(2);
372  os << std::setw(10) << std::left << state_->searchSize;
373  os << std::setw(10) << std::left << sigma_;
374  os << std::setw(10) << std::left << feasTolerance_;
375  os << std::setw(10) << std::left << optTolerance_;
376  os << std::scientific << std::setprecision(6);
377  os << std::setw(8) << std::left << state_->nfval;
378  os << std::setw(8) << std::left << state_->ngrad;
379  os << std::setw(8) << std::left << state_->ncval;
380  os << std::setw(8) << std::left << subproblemIter_;
381  os << std::endl;
382  }
383  os.flags(osFlags);
384 }
385 
386 } // namespace TypeE
387 } // namespace ROL
388 
389 #endif
void check(bool printToStream=false, std::ostream &outStream=std::cout) const
Run vector, linearity and derivative checks for user-supplied vectors, objective function and constra...
Provides the interface to evaluate objective functions.
const Ptr< Constraint< Real > > & getConstraint()
Get the equality constraint.
const Ptr< Vector< Real > > & getPrimalOptimizationVector()
Get the primal optimization space vector.
virtual ROL::Ptr< Vector > clone() const =0
Clone to make a new (uninitialized) vector.
virtual int dimension() const
Return dimension of the vector space.
Definition: ROL_Vector.hpp:162
void addBoundConstraint(const Ptr< BoundConstraint< Real >> &bnd)
Add a bound constraint.
const Ptr< const Vector< Real > > getConstraintVec(const Vector< Real > &x, Real &tol)
virtual ROL::Ptr< Vector > basis(const int i) const
Return i-th basis vector.
Definition: ROL_Vector.hpp:148
virtual void axpy(const Real alpha, const Vector &x)
Compute where .
Definition: ROL_Vector.hpp:119
void addLinearConstraint(std::string name, const Ptr< Constraint< Real >> &linear_econ, const Ptr< Vector< Real >> &linear_emul, const Ptr< Vector< Real >> &linear_eres=nullPtr, bool reset=false)
Add a linear equality constraint.
int getNumberFunctionEvaluations(void) const
const Ptr< AugmentedLagrangianObjective< Real > > getAugmentedLagrangian(void) const
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:46
virtual void finalize(bool lumpConstraints=false, bool printToStream=false, std::ostream &outStream=std::cout)
Tranform user-supplied constraints to consist of only bounds and equalities. Optimization problem can...
Real getObjectiveValue(const Vector< Real > &x, Real &tol)
Provides an interface to check status of optimization algorithms for problems with equality constrain...
void setScaling(const Real fscale=1.0, const Real cscale=1.0)
Provides the interface to evaluate the elastic augmented Lagrangian.
void initialize(Vector< Real > &x, const Vector< Real > &g, const Vector< Real > &l, const Vector< Real > &c, ElasticObjective< Real > &alobj, Constraint< Real > &con, std::ostream &outStream=std::cout)
const Ptr< Objective< Real > > & getObjective()
Get the objective function.
const Ptr< const Vector< Real > > getObjectiveGradient(const Vector< Real > &x, Real &tol)
const Ptr< AlgorithmState< Real > > state_
int getNumberConstraintEvaluations(void) const
Provides interface for and implements limited-memory secant operators.
Definition: ROL_Secant.hpp:45
const Ptr< Vector< Real > > & getResidualVector()
Get the primal constraint space vector.
const Ptr< Vector< Real > > & getMultiplierVector()
Get the dual constraint space vector.
void finalizeIteration()
Transform the optimization variables to the native parameterization after an optimization algorithm h...
virtual void run(Problem< Real > &problem, std::ostream &outStream=std::cout) override
Run algorithm on equality constrained problems (Type-E). This is the primary Type-E interface...
const Ptr< CombinedStatusTest< Real > > status_
int getNumberGradientEvaluations(void) const
const Ptr< PolyhedralProjection< Real > > & getPolyhedralProjection()
Get the polyhedral projection object. This is a null pointer if no linear constraints and/or bounds a...
EProblem getProblemType()
Get the optimization problem type (U, B, E, or G).
virtual void applyAdjointJacobian(Vector< Real > &ajv, const Vector< Real > &v, const Vector< Real > &x, Real &tol)
Apply the adjoint of the the constraint Jacobian at , , to vector .
virtual void writeExitStatus(std::ostream &os) const
void initialize(const Vector< Real > &x, const Vector< Real > &g, const Vector< Real > &mul, const Vector< Real > &c)
virtual void set(const Vector &x)
Set where .
Definition: ROL_Vector.hpp:175
StabilizedLCLAlgorithm(ParameterList &list, const Ptr< Secant< Real >> &secant=nullPtr)
void reset(const Vector< Real > &multiplier, Real penaltyParameter, Real sigma)
virtual void edit()
Resume editting optimization problem after finalize has been called.
const Ptr< Vector< Real > > & getDualOptimizationVector()
Get the dual optimization space vector.
virtual void writeName(std::ostream &os) const override
Print step name.
Defines the general constraint operator interface.
virtual void writeOutput(std::ostream &os, const bool print_header=false) const override
Print iterate status.
virtual void writeHeader(std::ostream &os) const override
Print iterate header.