44 #ifndef ROL_TYPEB_PRIMALDUALACTIVESETALGORITHM_DEF_HPP
45 #define ROL_TYPEB_PRIMALDUALACTIVESETALGORITHM_DEF_HPP
50 template<
typename Real>
60 secantName_ = list.sublist(
"General").sublist(
"Secant").get(
"Type",
"Limited-Memory BFGS");
62 secant_ = SecantFactory<Real>(list);
65 secantName_ = list.sublist(
"General").sublist(
"Secant").get(
"User Defined Secant Name",
66 "Unspecified User Defined Secant Method");
68 useSecantHessVec_ = list.sublist(
"General").sublist(
"Secant").get(
"Use as Hessian",
false);
69 useSecantPrecond_ = list.sublist(
"General").sublist(
"Secant").get(
"Use as Preconditioner",
false);
72 maxit_ = list.sublist(
"Step").sublist(
"Primal Dual Active Set").get(
"Iteration Limit", 10);
73 stol_ = list.sublist(
"Step").sublist(
"Primal Dual Active Set").get(
"Relative Step Tolerance", 1e-8);
74 gtol_ = list.sublist(
"Step").sublist(
"Primal Dual Active Set").get(
"Relative Gradient Tolerance", 1e-6);
75 scale_ = list.sublist(
"Step").sublist(
"Primal Dual Active Set").get(
"Dual Scaling", 1.0);
78 atolKrylov_ = list.sublist(
"General").sublist(
"Krylov").get(
"Absolute Tolerance", 1e-4);
79 rtolKrylov_ = list.sublist(
"General").sublist(
"Krylov").get(
"Relative Tolerance", 1e-2);
80 maxitKrylov_ = list.sublist(
"General").sublist(
"Krylov").get(
"Iteration Limit", 100);
82 verbosity_ = list.sublist(
"General").get(
"Output Level", 0);
86 template<
typename Real>
91 std::ostream &outStream) {
93 if (proj_ == nullPtr) {
94 proj_ = makePtr<PolyhedralProjection<Real>>(makePtrFromRef(bnd));
100 list.sublist(
"General").sublist(
"Krylov").set(
"Absolute Tolerance", atolKrylov_);
101 list.sublist(
"General").sublist(
"Krylov").set(
"Relative Tolerance", rtolKrylov_);
102 list.sublist(
"General").sublist(
"Krylov").set(
"Iteration Limit", maxitKrylov_);
103 krylovName_ =
"GMRES";
104 krylov_ = makePtr<GMRES<Real>>(list);
108 krylov_ = makePtr<ConjugateResiduals<Real>>(atolKrylov_,rtolKrylov_,maxitKrylov_);
115 Real ftol = std::sqrt(ROL_EPSILON<Real>());
116 proj_->project(x,outStream);
117 state_->iterateVec->set(x);
119 state_->value = obj.
value(x,ftol); state_->nfval++;
120 obj.
gradient(*state_->gradientVec,x,ftol); state_->ngrad++;
121 state_->stepVec->set(x);
122 state_->stepVec->axpy(-one,state_->gradientVec->dual());
123 proj_->project(*state_->stepVec,outStream);
124 state_->stepVec->axpy(-one,x);
125 state_->gnorm = state_->stepVec->norm();
126 state_->snorm = ROL_INF<Real>();
129 template<
typename Real>
134 std::ostream &outStream ) {
135 const Real
zero(0), one(1);
137 initialize(x,g,obj,bnd,outStream);
139 Ptr<Vector<Real>> lambda = x.
clone(), gtmp = g.
clone();
140 Ptr<Vector<Real>> pwa = x.
clone(), dwa = g.
clone();
141 Ptr<Vector<Real>> mu, b, r;
143 mu = proj_->getMultiplier()->clone(); mu->zero();
144 b = proj_->getResidual()->clone();
145 r = proj_->getResidual()->clone();
147 lambda->set(state_->gradientVec->dual());
149 Real xnorm(0), snorm(0), rnorm(0), tol(std::sqrt(ROL_EPSILON<Real>()));
151 Ptr<LinearOperator<Real>> hessian, precond;
154 if (verbosity_ > 0) writeOutput(outStream,
true);
156 while (status_->check(*state_)) {
158 state_->stepVec->zero();
161 proj_->getLinearConstraint()->value(*r,x,tol);
163 for ( iter_ = 0; iter_ < maxit_; iter_++ ) {
168 xlam->axpy(scale_,*lambda);
175 xtmp->axpy(-one,*state_->iterateVec);
180 xtmp->axpy(-one,*state_->iterateVec);
186 if ( useSecantHessVec_ && secant_ != nullPtr ) {
187 secant_->applyB(*gtmp,*As);
190 obj.
hessVec(*gtmp,*As,*state_->iterateVec,itol_);
193 proj_->getLinearConstraint()->applyJacobian(*b,*As,*state_->iterateVec,tol);
197 gtmp->plus(*state_->gradientVec);
204 rnorm = std::sqrt(gtmp->dot(*gtmp)+b->dot(*b));
207 rnorm = gtmp->norm();
209 if ( rnorm >
zero ) {
212 hessian = makePtr<HessianPDAS_Poly>(makePtrFromRef(obj),makePtrFromRef(bnd),
213 proj_->getLinearConstraint(),state_->iterateVec,xlam,neps_,secant_,
214 useSecantHessVec_,pwa,dwa);
215 precond = makePtr<PrecondPDAS_Poly>(makePtrFromRef(obj),makePtrFromRef(bnd),
216 state_->iterateVec,xlam,neps_,secant_,useSecantPrecond_,dwa);
219 krylov_->run(sol,*hessian,rhs,*precond,iterKrylov_,flagKrylov_);
223 hessian = makePtr<HessianPDAS>(makePtrFromRef(obj),makePtrFromRef(bnd),
224 state_->iterateVec,xlam,neps_,secant_,useSecantHessVec_,pwa);
225 precond = makePtr<PrecondPDAS>(makePtrFromRef(obj),makePtrFromRef(bnd),
226 state_->iterateVec,xlam,neps_,secant_,useSecantPrecond_,dwa);
227 krylov_->run(*state_->stepVec,*hessian,*gtmp,*precond,iterKrylov_,flagKrylov_);
229 totalKrylov_ += iterKrylov_;
232 state_->stepVec->plus(*As);
236 x.
set(*state_->iterateVec);
237 x.
plus(*state_->stepVec);
238 snorm = state_->stepVec->norm();
240 if ( useSecantHessVec_ && secant_ != nullPtr ) {
241 secant_->applyB(*gtmp,*state_->stepVec);
244 obj.
hessVec(*gtmp,*state_->stepVec,*state_->iterateVec,itol_);
247 proj_->getLinearConstraint()->applyAdjointJacobian(*dwa,*mu,*state_->iterateVec,tol);
250 gtmp->plus(*state_->gradientVec);
252 lambda->set(gtmp->dual());
261 if ( xtmp->norm() < gtol_*state_->gnorm ) {
265 if ( snorm < stol_*xnorm ) {
270 if ( iter_ == maxit_ ) {
279 state_->iterateVec->set(x);
281 state_->snorm = snorm;
283 state_->value = obj.
value(x,tol); state_->nfval++;
285 if ( secant_ != nullPtr ) {
286 gtmp->set(*state_->gradientVec);
288 obj.
gradient(*state_->gradientVec,x,tol); state_->ngrad++;
289 xtmp->set(x); xtmp->axpy(-one,state_->gradientVec->dual());
290 proj_->project(*xtmp,outStream);
292 state_->gnorm = xtmp->norm();
293 if ( secant_ != nullPtr ) {
294 secant_->updateStorage(x,*state_->gradientVec,*gtmp,*state_->stepVec,state_->snorm,state_->iter+1);
298 if (verbosity_ > 0) writeOutput(outStream,writeHeader_);
303 template<
typename Real>
305 std::ios_base::fmtflags osFlags(os.flags());
306 if (verbosity_ > 1) {
307 os << std::string(114,
'-') << std::endl;
308 if (!useSecantHessVec_) {
309 os <<
"Primal Dual Active Set Newton's Method";
312 os <<
"Primal Dual Active Set Quasi-Newton Method with " << secantName_ <<
" Hessian approximation";
314 os <<
" status output definitions" << std::endl << std::endl;
315 os <<
" iter - Number of iterates (steps taken)" << std::endl;
316 os <<
" value - Objective function value" << std::endl;
317 os <<
" gnorm - Norm of the gradient" << std::endl;
318 os <<
" snorm - Norm of the step (update to optimization vector)" << std::endl;
319 os <<
" #fval - Cumulative number of times the objective function was evaluated" << std::endl;
320 os <<
" #grad - Cumulative number of times the gradient was computed" << std::endl;
322 os <<
" iterPDAS - Number of Primal Dual Active Set iterations" << std::endl << std::endl;
323 os <<
" flagPDAS - Primal Dual Active Set flag" << std::endl;
324 os <<
" iterK - Number of Krylov iterations" << std::endl << std::endl;
327 os <<
" iterK - Number of Krylov iterations" << std::endl << std::endl;
328 os <<
" flagK - Krylov flag" << std::endl;
334 os <<
" feasible - Is iterate feasible?" << std::endl;
335 os << std::string(114,
'-') << std::endl;
339 os << std::setw(6) << std::left <<
"iter";
340 os << std::setw(15) << std::left <<
"value";
341 os << std::setw(15) << std::left <<
"gnorm";
342 os << std::setw(15) << std::left <<
"snorm";
343 os << std::setw(10) << std::left <<
"#fval";
344 os << std::setw(10) << std::left <<
"#grad";
346 os << std::setw(10) << std::left <<
"iterPDAS";
347 os << std::setw(10) << std::left <<
"flagPDAS";
348 os << std::setw(10) << std::left <<
"iterK";
351 os << std::setw(10) << std::left <<
"iterK";
352 os << std::setw(10) << std::left <<
"flagK";
354 os << std::setw(10) << std::left <<
"feasible";
359 template<
typename Real>
361 std::ios_base::fmtflags osFlags(os.flags());
362 if (!useSecantHessVec_) {
363 os << std::endl <<
"Primal Dual Active Set Newton's Method (Type B, Bound Constraints)" << std::endl;
366 os << std::endl <<
"Primal Dual Active Set Quasi-Newton Method with "
367 << secantName_ <<
" Hessian approximation" << std::endl;
372 template<
typename Real>
374 std::ios_base::fmtflags osFlags(os.flags());
375 os << std::scientific << std::setprecision(6);
376 if ( state_->iter == 0 ) writeName(os);
377 if ( write_header ) writeHeader(os);
378 if ( state_->iter == 0 ) {
380 os << std::setw(6) << std::left << state_->iter;
381 os << std::setw(15) << std::left << state_->value;
382 os << std::setw(15) << std::left << state_->gnorm;
383 os << std::setw(15) << std::left <<
"---";
384 os << std::setw(10) << std::left << state_->nfval;
385 os << std::setw(10) << std::left << state_->ngrad;
386 os << std::setw(10) << std::left <<
"---";
387 os << std::setw(10) << std::left <<
"---";
389 os << std::setw(10) << std::left <<
"---";
392 os << std::setw(10) << std::left <<
"YES";
395 os << std::setw(10) << std::left <<
"NO";
401 os << std::setw(6) << std::left << state_->iter;
402 os << std::setw(15) << std::left << state_->value;
403 os << std::setw(15) << std::left << state_->gnorm;
404 os << std::setw(15) << std::left << state_->snorm;
405 os << std::setw(10) << std::left << state_->nfval;
406 os << std::setw(10) << std::left << state_->ngrad;
408 os << std::setw(10) << std::left << iter_;
409 os << std::setw(10) << std::left << flag_;
410 os << std::setw(10) << std::left << totalKrylov_;
413 os << std::setw(10) << std::left << iterKrylov_;
414 os << std::setw(10) << std::left << flagKrylov_;
417 os << std::setw(10) << std::left <<
"YES";
420 os << std::setw(10) << std::left <<
"NO";
std::string ECGFlagToString(ECGFlag cgf)
virtual bool isFeasible(const Vector< Real > &v)
Check if the vector, v, is feasible.
bool useSecantPrecond_
Whether or not to use a secant approximation to precondition inexact Newton.
Provides the interface to evaluate objective functions.
void initialize(Vector< Real > &x, const Vector< Real > &g, Objective< Real > &obj, BoundConstraint< Real > &bnd, std::ostream &outStream=std::cout)
Real stol_
PDAS minimum step size stopping tolerance (default: 1e-8)
virtual ROL::Ptr< Vector > clone() const =0
Clone to make a new (uninitialized) vector.
virtual void plus(const Vector &x)=0
Compute , where .
Real gtol_
PDAS gradient stopping tolerance (default: 1e-6)
virtual Real value(const Vector< Real > &x, Real &tol)=0
Compute value.
Defines the linear algebra of vector space on a generic partitioned vector.
virtual void hessVec(Vector< Real > &hv, const Vector< Real > &v, const Vector< Real > &x, Real &tol)
Apply Hessian approximation to vector.
Ptr< Secant< Real > > secant_
Secant object (used for quasi-Newton)
virtual void writeExitStatus(std::ostream &os) const
void pruneUpperInactive(Vector< Real > &v, const Vector< Real > &x, Real eps=Real(0))
Set variables to zero if they correspond to the -inactive set.
ESecant StringToESecant(std::string s)
Defines the linear algebra or vector space interface.
virtual void update(const Vector< Real > &x, UpdateType type, int iter=-1)
Update objective function.
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
virtual const Ptr< const Vector< Real > > getLowerBound(void) const
Return the ref count pointer to the lower bound vector.
EKrylov StringToEKrylov(std::string s)
Real rtolKrylov_
Relative tolerance for Krylov solve (default: 1e-2)
PrimalDualActiveSetAlgorithm(ParameterList &list, const Ptr< Secant< Real >> &secant=nullPtr)
virtual void gradient(Vector< Real > &g, const Vector< Real > &x, Real &tol)
Compute gradient.
std::string NumberToString(T Number)
Real scale_
Scale for dual variables in the active set, (default: 1)
std::string secantName_
Secant name.
void pruneLowerInactive(Vector< Real > &v, const Vector< Real > &x, Real eps=Real(0))
Set variables to zero if they correspond to the -inactive set.
ESecant esec_
Secant type.
void run(Vector< Real > &x, const Vector< Real > &g, Objective< Real > &obj, BoundConstraint< Real > &bnd, std::ostream &outStream=std::cout) override
Run algorithm on bound constrained problems (Type-B). This general interface supports the use of dual...
Provides interface for and implements limited-memory secant operators.
Provides an interface to check status of optimization algorithms.
virtual void project(Vector< Real > &x)
Project optimization variables onto the bounds.
void writeOutput(std::ostream &os, const bool write_header=false) const override
Print iterate status.
virtual const Ptr< const Vector< Real > > getUpperBound(void) const
Return the ref count pointer to the upper bound vector.
void pruneInactive(Vector< Real > &v, const Vector< Real > &x, Real eps=Real(0))
Set variables to zero if they correspond to the -inactive set.
void pruneActive(Vector< Real > &v, const Vector< Real > &x, Real eps=Real(0))
Set variables to zero if they correspond to the -active set.
Provides the interface to apply upper and lower bound constraints.
int maxit_
Maximum number of PDAS steps (default: 10)
bool useSecantHessVec_
Whether or not to use to a secant approximation as the Hessian.
void initialize(const Vector< Real > &x, const Vector< Real > &g)
void writeHeader(std::ostream &os) const override
Print iterate header.
virtual void set(const Vector &x)
Set where .
int maxitKrylov_
Maximum number of Krylov iterations (default: 100)
virtual Real norm() const =0
Returns where .
Real ROL_EPSILON(void)
Platform-dependent machine epsilon.
void writeName(std::ostream &os) const override
Print step name.
Real atolKrylov_
Absolute tolerance for Krylov solve (default: 1e-4)
const Ptr< CombinedStatusTest< Real > > status_