ROL
ROL_TypeG_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_TYPEG_STABILIZEDLCLALGORITHM_DEF_H
11#define ROL_TYPEG_STABILIZEDLCLALGORITHM_DEF_H
12
14#include "ROL_Bounds.hpp"
15
16namespace ROL {
17namespace TypeG {
18
19template<typename Real>
21 : TypeG::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,
74 std::ostream &outStream ) {
75 hasPolyProj_ = true;
76 if (proj_ == nullPtr) {
77 proj_ = makePtr<PolyhedralProjection<Real>>(makePtrFromRef(bnd));
78 hasPolyProj_ = false;
79 }
80 proj_->project(x,outStream);
81
82 const Real one(1), TOL(1.e-2);
83 Real tol = std::sqrt(ROL_EPSILON<Real>());
85
86 // Initialize the algorithm state
87 state_->nfval = 0;
88 state_->ncval = 0;
89 state_->ngrad = 0;
90
91 // Compute objective value
92 alobj.getAugmentedLagrangian()->update(x,UpdateType::Initial,state_->iter);
93 state_->value = alobj.getObjectiveValue(x,tol);
94 alobj.getAugmentedLagrangian()->gradient(*state_->gradientVec,x,tol);
95
96 // Compute constraint violation
97 state_->constraintVec->set(*alobj.getConstraintVec(x,tol));
98 state_->cnorm = state_->constraintVec->norm();
99
100 // Update evaluation counters
101 state_->ncval += alobj.getNumberConstraintEvaluations();
102 state_->nfval += alobj.getNumberFunctionEvaluations();
103 state_->ngrad += alobj.getNumberGradientEvaluations();
104
105 // Compute problem scaling
106 if (useDefaultScaling_) {
107 fscale_ = one/std::max(one,alobj.getObjectiveGradient(x,tol)->norm());
108 try {
109 Ptr<Vector<Real>> ji = x.clone();
110 Real maxji(0), normji(0);
111 for (int i = 0; i < c.dimension(); ++i) {
112 con.applyAdjointJacobian(*ji,*c.basis(i),x,tol);
113 normji = ji->norm();
114 maxji = std::max(normji,maxji);
115 }
116 cscale_ = one/std::max(one,maxji);
117 }
118 catch (std::exception &e) {
119 cscale_ = one;
120 }
121 }
123
124 // Compute gradient of the lagrangian
125 x.axpy(-one,state_->gradientVec->dual());
126 proj_->project(x,outStream);
127 x.axpy(-one/std::min(fscale_,cscale_),*state_->iterateVec);
128 state_->gnorm = x.norm();
129 x.set(*state_->iterateVec);
130
131 // Compute initial penalty parameter
132 if (useDefaultInitPen_) {
133 const Real oem8(1e-8), oem2(1e-2), two(2), ten(10);
134 state_->searchSize = std::max(oem8,
135 std::min(ten*std::max(one,std::abs(fscale_*state_->value))
136 / std::max(one,std::pow(cscale_*state_->cnorm,two)),oem2*maxPenaltyParam_));
137 }
138 // Initialize intermediate stopping tolerances
139 optTolerance_ = std::max<Real>(TOL*outerOptTolerance_,
141 //optTolerance_ = std::min<Real>(optTolerance_,TOL*state_->gnorm);
142 feasTolerance_ = std::max<Real>(TOL*outerFeasTolerance_,
144
145 // Set data
146 alobj.reset(l,state_->searchSize,sigma_);
147
148 if (verbosity_ > 1) {
149 outStream << std::endl;
150 outStream << "Stabilized LCL Initialize" << std::endl;
151 outStream << "Objective Scaling: " << fscale_ << std::endl;
152 outStream << "Constraint Scaling: " << cscale_ << std::endl;
153 outStream << "Penalty Parameter: " << state_->searchSize << std::endl;
154 outStream << std::endl;
155 }
156}
157
158template<typename Real>
160 std::ostream &outStream ) {
161 if (problem.getProblemType() == TYPE_EB) {
162 problem.edit();
163 problem.finalize(true,verbosity_>3,outStream); // Lump linear and nonlinear constraints
165 *problem.getDualOptimizationVector(),
166 *problem.getObjective(),
167 *problem.getBoundConstraint(),
168 *problem.getConstraint(),
169 *problem.getMultiplierVector(),
170 *problem.getResidualVector(),
171 outStream);
172 problem.finalizeIteration();
173 }
174 else {
175 throw Exception::NotImplemented(">>> ROL::TypeG::Algorithm::run : Optimization problem is not Type G!");
176 }
177}
178
179template<typename Real>
181 const Vector<Real> &g,
182 Objective<Real> &obj,
184 Constraint<Real> &econ,
185 Vector<Real> &emul,
186 const Vector<Real> &eres,
187 std::ostream &outStream ) {
188 const Real one(1), oem2(1e-2);
189 Real tol(std::sqrt(ROL_EPSILON<Real>())), cnorm(0), lnorm;;
190 // Initialize augmented Lagrangian data
191 ElasticObjective<Real> alobj(makePtrFromRef(obj),makePtrFromRef(econ),
192 state_->searchSize,sigma_,g,eres,emul,
194 initialize(x,g,emul,eres,alobj,bnd,econ,outStream);
195 // Define Elastic Subproblem
196 Ptr<Vector<Real>> u = eres.clone(), v = eres.clone(), c = eres.clone();
197 Ptr<Vector<Real>> gu = emul.clone(), gv = emul.clone(), l = emul.clone();
198 Ptr<Vector<Real>> s = x.clone(), gs = g.clone(), cvec = eres.clone();
199 Ptr<ElasticLinearConstraint<Real>> lcon
200 = makePtr<ElasticLinearConstraint<Real>>(makePtrFromRef(x),
201 makePtrFromRef(econ),
202 makePtrFromRef(eres));
203 std::vector<Ptr<Vector<Real>>> vecList = {s,u,v};
204 Ptr<PartitionedVector<Real>> xp = makePtr<PartitionedVector<Real>>(vecList);
205 Ptr<PartitionedVector<Real>> gxp = makePtr<PartitionedVector<Real>>({gs,gu,gv});
206 Ptr<Vector<Real>> lb = u->clone(); lb->zero();
207 std::vector<Ptr<BoundConstraint<Real>>> bndList(3);
208 bndList[0] = makePtrFromRef(bnd);
209 bndList[1] = makePtr<Bounds<Real>>(*lb,true);
210 bndList[2] = makePtr<Bounds<Real>>(*lb,true);
211 Ptr<BoundConstraint<Real>> xbnd
212 = makePtr<BoundConstraint_Partitioned<Real>>(bndList,vecList);
213 ParameterList ppa_list;
214 if (c->dimension() == 1)
215 ppa_list.sublist("General").sublist("Polyhedral Projection").set("Type","Dai-Fletcher");
216 else
217 ppa_list.sublist("General").sublist("Polyhedral Projection").set("Type","Semismooth Newton");
218 Problem<Real> elc(makePtrFromRef(alobj),xp,gxp);
219 elc.addBoundConstraint(xbnd);
220 elc.addLinearConstraint("ElasticLinearConstraint",lcon,l,c);
221 elc.setProjectionAlgorithm(ppa_list);
222 elc.finalize(false,verbosity_>2,outStream);
223
224 // Initialize subproblem algorithm
225 Ptr<TypeB::Algorithm<Real>> algo;
226
227 // Output
228 if (verbosity_ > 0) writeOutput(outStream,true);
229
230 while (status_->check(*state_)) {
231 lcon->setAnchor(state_->iterateVec);
232 if (verbosity_ > 3) elc.check(true,outStream);
233
234 // Solve linearly constrained augmented Lagrangian subproblem
235 list_.sublist("Status Test").set("Gradient Tolerance",optTolerance_);
236 list_.sublist("Status Test").set("Step Tolerance",1.e-6*optTolerance_);
238 algo->run(elc,outStream);
239 x.set(*xp->get(0));
240
241 // Update evaluation counters
242 subproblemIter_ = algo->getState()->iter;
243 state_->nfval += alobj.getNumberFunctionEvaluations();
244 state_->ngrad += alobj.getNumberGradientEvaluations();
245 state_->ncval += alobj.getNumberConstraintEvaluations();
246
247 // Compute step
248 state_->stepVec->set(x);
249 state_->stepVec->axpy(-one,*state_->iterateVec);
250 state_->snorm = state_->stepVec->norm();
251
252 // Update iteration information
253 state_->iter++;
254 cvec->set(*alobj.getConstraintVec(x,tol));
255 cnorm = cvec->norm();
256 if ( cscale_*cnorm < feasTolerance_ ) {
257 // Update iteration information
258 state_->iterateVec->set(x);
259 state_->value = alobj.getObjectiveValue(x,tol);
260 state_->constraintVec->set(*cvec);
261 state_->cnorm = cnorm;
262
263 // Update multipliers
264 emul.axpy(static_cast<Real>(-1),*elc.getPolyhedralProjection()->getMultiplier());
265 emul.axpy(state_->searchSize*cscale_,state_->constraintVec->dual());
266
267 alobj.getAugmentedLagrangian()->gradient(*state_->gradientVec,x,tol);
268 if (scaleLagrangian_) state_->gradientVec->scale(state_->searchSize);
269 econ.applyAdjointJacobian(*gs,*elc.getPolyhedralProjection()->getMultiplier(),x,tol);
270 state_->gradientVec->axpy(-cscale_,*gs);
271 x.axpy(-one/std::min(fscale_,cscale_),state_->gradientVec->dual());
272 proj_->project(x,outStream);
273 x.axpy(-one,*state_->iterateVec);
274 state_->gnorm = x.norm();
275 x.set(*state_->iterateVec);
276
277 // Update subproblem information
278 lnorm = elc.getPolyhedralProjection()->getMultiplier()->norm();
279 sigma_ = std::min(one+lnorm,sigmaMax_)/(one+state_->searchSize);
280 if ( algo->getState()->statusFlag == EXITSTATUS_CONVERGED ) {
281 optTolerance_ = std::max(oem2*outerOptTolerance_,
282 optTolerance_/(one + std::pow(state_->searchSize,optIncreaseExponent_)));
283 }
284 feasTolerance_ = std::max(oem2*outerFeasTolerance_,
285 feasTolerance_/(one + std::pow(state_->searchSize,feasIncreaseExponent_)));
286
287 // Update Algorithm State
288 state_->snorm += lnorm + state_->searchSize*cscale_*state_->cnorm;
289 state_->lagmultVec->set(emul);
290 }
291 else {
292 // Update subproblem information
293 state_->searchSize = std::min(penaltyUpdate_*state_->searchSize,maxPenaltyParam_);
295 optTolerance_ = std::max(oem2*outerOptTolerance_,
296 optToleranceInitial_/(one + std::pow(state_->searchSize,optDecreaseExponent_)));
297 feasTolerance_ = std::max(oem2*outerFeasTolerance_,
298 feasToleranceInitial_/(one + std::pow(state_->searchSize,feasDecreaseExponent_)));
299 }
300 alobj.reset(emul,state_->searchSize,sigma_);
301
302 // Update Output
303 if (verbosity_ > 0) writeOutput(outStream,printHeader_);
304 }
306}
307
308template<typename Real>
309void StabilizedLCLAlgorithm<Real>::writeHeader( std::ostream& os ) const {
310 std::ios_base::fmtflags osFlags(os.flags());
311 if(verbosity_>1) {
312 os << std::string(114,'-') << std::endl;
313 os << "Stabilized LCL status output definitions" << std::endl << std::endl;
314 os << " iter - Number of iterates (steps taken)" << std::endl;
315 os << " fval - Objective function value" << std::endl;
316 os << " cnorm - Norm of the constraint violation" << std::endl;
317 os << " gLnorm - Norm of the gradient of the Lagrangian" << std::endl;
318 os << " snorm - Norm of the step" << std::endl;
319 os << " penalty - Penalty parameter" << std::endl;
320 os << " sigma - Elastic Penalty parameter" << std::endl;
321 os << " feasTol - Feasibility tolerance" << std::endl;
322 os << " optTol - Optimality tolerance" << std::endl;
323 os << " #fval - Number of times the objective was computed" << std::endl;
324 os << " #grad - Number of times the gradient was computed" << std::endl;
325 os << " #cval - Number of times the constraint was computed" << std::endl;
326 os << " subIter - Number of iterations to solve subproblem" << std::endl;
327 os << std::string(114,'-') << std::endl;
328 }
329 os << " ";
330 os << std::setw(6) << std::left << "iter";
331 os << std::setw(15) << std::left << "fval";
332 os << std::setw(15) << std::left << "cnorm";
333 os << std::setw(15) << std::left << "gLnorm";
334 os << std::setw(15) << std::left << "snorm";
335 os << std::setw(10) << std::left << "penalty";
336 os << std::setw(10) << std::left << "sigma";
337 os << std::setw(10) << std::left << "feasTol";
338 os << std::setw(10) << std::left << "optTol";
339 os << std::setw(8) << std::left << "#fval";
340 os << std::setw(8) << std::left << "#grad";
341 os << std::setw(8) << std::left << "#cval";
342 os << std::setw(8) << std::left << "subIter";
343 os << std::endl;
344 os.flags(osFlags);
345}
346
347template<typename Real>
348void StabilizedLCLAlgorithm<Real>::writeName( std::ostream& os ) const {
349 std::ios_base::fmtflags osFlags(os.flags());
350 os << std::endl << "Stabilized LCL Solver (Type G, General Constraints)";
351 os << std::endl;
352 os << "Subproblem Solver: " << subStep_ << std::endl;
353 os.flags(osFlags);
354}
355
356template<typename Real>
357void StabilizedLCLAlgorithm<Real>::writeOutput( std::ostream& os, const bool print_header ) const {
358 std::ios_base::fmtflags osFlags(os.flags());
359 os << std::scientific << std::setprecision(6);
360 if ( state_->iter == 0 ) writeName(os);
361 if ( print_header ) writeHeader(os);
362 if ( state_->iter == 0 ) {
363 os << " ";
364 os << std::setw(6) << std::left << state_->iter;
365 os << std::setw(15) << std::left << state_->value;
366 os << std::setw(15) << std::left << state_->cnorm;
367 os << std::setw(15) << std::left << state_->gnorm;
368 os << std::setw(15) << std::left << "---";
369 os << std::scientific << std::setprecision(2);
370 os << std::setw(10) << std::left << state_->searchSize;
371 os << std::setw(10) << std::left << sigma_;
372 os << std::setw(10) << std::left << std::max(feasTolerance_,outerFeasTolerance_);
373 os << std::setw(10) << std::left << std::max(optTolerance_,outerOptTolerance_);
374 os << std::scientific << std::setprecision(6);
375 os << std::setw(8) << std::left << state_->nfval;
376 os << std::setw(8) << std::left << state_->ngrad;
377 os << std::setw(8) << std::left << state_->ncval;
378 os << std::setw(8) << std::left << "---";
379 os << std::endl;
380 }
381 else {
382 os << " ";
383 os << std::setw(6) << std::left << state_->iter;
384 os << std::setw(15) << std::left << state_->value;
385 os << std::setw(15) << std::left << state_->cnorm;
386 os << std::setw(15) << std::left << state_->gnorm;
387 os << std::setw(15) << std::left << state_->snorm;
388 os << std::scientific << std::setprecision(2);
389 os << std::setw(10) << std::left << state_->searchSize;
390 os << std::setw(10) << std::left << sigma_;
391 os << std::setw(10) << std::left << feasTolerance_;
392 os << std::setw(10) << std::left << optTolerance_;
393 os << std::scientific << std::setprecision(6);
394 os << std::setw(8) << std::left << state_->nfval;
395 os << std::setw(8) << std::left << state_->ngrad;
396 os << std::setw(8) << std::left << state_->ncval;
397 os << std::setw(8) << std::left << subproblemIter_;
398 os << std::endl;
399 }
400 os.flags(osFlags);
401}
402
403} // namespace TypeG
404} // namespace ROL
405
406#endif
virtual void initialize(const Vector< Real > &x)
Initialize temporary variables.
Provides the interface to apply upper and lower bound constraints.
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 setProjectionAlgorithm(ParameterList &parlist)
Set polyhedral projection algorithm.
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< BoundConstraint< Real > > & getBoundConstraint()
Get the bound constraint.
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.
Provides interface for and implements limited-memory secant operators.
Algorithm()
Constructor, given a step and a status test.
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
const Ptr< CombinedStatusTest< Real > > status_
Ptr< PolyhedralProjection< Real > > proj_
const Ptr< AlgorithmState< Real > > state_
virtual void run(Problem< Real > &problem, std::ostream &outStream=std::cout) override
Run algorithm on general constrained problems (Type-G). This is the primary Type-G interface.
void initialize(Vector< Real > &x, const Vector< Real > &g, const Vector< Real > &l, const Vector< Real > &c, ElasticObjective< Real > &alobj, BoundConstraint< Real > &bnd, Constraint< Real > &con, std::ostream &outStream=std::cout)
virtual void writeName(std::ostream &os) const override
Print step name.
StabilizedLCLAlgorithm(ParameterList &list, const Ptr< Secant< Real > > &secant=nullPtr)
virtual void writeHeader(std::ostream &os) const override
Print iterate header.
virtual void writeOutput(std::ostream &os, const bool print_header=false) const override
Print iterate status.
Defines the linear algebra or vector space interface.
virtual Real norm() const =0
Returns where .
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_EB
@ EXITSTATUS_CONVERGED
Definition ROL_Types.hpp:84