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
16namespace ROL {
17namespace TypeE {
18
19template<typename Real>
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
66template<typename Real>
68 const Vector<Real> &g,
69 const Vector<Real> &l,
70 const Vector<Real> &c,
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
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 }
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_,
129 //optTolerance_ = std::min<Real>(optTolerance_,TOL*state_->gnorm);
130 feasTolerance_ = std::max<Real>(TOL*outerFeasTolerance_,
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
146template<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
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
166template<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,
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_);
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_);
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 }
289}
290
291template<typename Real>
292void 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
330template<typename Real>
331void 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
339template<typename Real>
340void 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
virtual void initialize(const Vector< Real > &x)
Initialize temporary variables.
Provides an interface to check status of optimization algorithms for problems with equality constrain...
Defines the general constraint operator interface.
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 .
Provides the interface to evaluate the elastic augmented Lagrangian.
void reset(const Vector< Real > &multiplier, Real penaltyParameter, Real sigma)
const Ptr< const Vector< Real > > getConstraintVec(const Vector< Real > &x, Real &tol)
const Ptr< const Vector< Real > > getObjectiveGradient(const Vector< Real > &x, Real &tol)
const Ptr< AugmentedLagrangianObjective< Real > > getAugmentedLagrangian(void) const
int getNumberConstraintEvaluations(void) const
Real getObjectiveValue(const Vector< Real > &x, Real &tol)
void setScaling(const Real fscale=1.0, const Real cscale=1.0)
Provides the interface to evaluate objective functions.
const Ptr< PolyhedralProjection< Real > > & getPolyhedralProjection()
Get the polyhedral projection object. This is a null pointer if no linear constraints and/or bounds a...
const Ptr< Vector< Real > > & getPrimalOptimizationVector()
Get the primal optimization space vector.
const Ptr< Vector< Real > > & getDualOptimizationVector()
Get the dual optimization space vector.
const Ptr< Vector< Real > > & getMultiplierVector()
Get the dual constraint space vector.
const Ptr< Constraint< Real > > & getConstraint()
Get the equality constraint.
EProblem getProblemType()
Get the optimization problem type (U, B, E, or G).
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.
void addBoundConstraint(const Ptr< BoundConstraint< Real > > &bnd)
Add a bound constraint.
void finalizeIteration()
Transform the optimization variables to the native parameterization after an optimization algorithm h...
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...
const Ptr< Objective< Real > > & getObjective()
Get the objective function.
const Ptr< Vector< Real > > & getResidualVector()
Get the primal constraint space vector.
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...
virtual void edit()
Resume editting optimization problem after finalize has been called.
const Ptr< CombinedStatusTest< Real > > status_
Algorithm()
Constructor, given a step and a status test.
const Ptr< AlgorithmState< Real > > state_
Provides interface for and implements limited-memory secant operators.
void initialize(const Vector< Real > &x, const Vector< Real > &g, const Vector< Real > &mul, const Vector< Real > &c)
virtual void writeExitStatus(std::ostream &os) const
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)
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.
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.
virtual void writeName(std::ostream &os) const override
Print step name.
StabilizedLCLAlgorithm(ParameterList &list, const Ptr< Secant< Real > > &secant=nullPtr)
Defines the linear algebra or vector space interface.
virtual void set(const Vector &x)
Set where .
virtual ROL::Ptr< Vector > clone() const =0
Clone to make a new (uninitialized) vector.
virtual int dimension() const
Return dimension of the vector space.
virtual ROL::Ptr< Vector > basis(const int i) const
Return i-th basis vector.
virtual void axpy(const Real alpha, const Vector &x)
Compute where .
Ptr< Algorithm< Real > > AlgorithmFactory(ParameterList &parlist, const Ptr< Secant< Real > > &secant=nullPtr)
Real ROL_EPSILON(void)
Platform-dependent machine epsilon.
Definition ROL_Types.hpp:57
@ TYPE_E
@ EXITSTATUS_CONVERGED
Definition ROL_Types.hpp:84