ROL
ROL_SemismoothNewtonProjection_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_SEMISMOOTHNEWTONPROJECTION_DEF_H
11#define ROL_SEMISMOOTHNEWTONPROJECTION_DEF_H
12
13namespace ROL {
14
15template<typename Real>
17 const Vector<Real> &xdual,
18 const Ptr<BoundConstraint<Real>> &bnd,
19 const Ptr<Constraint<Real>> &con,
20 const Vector<Real> &mul,
21 const Vector<Real> &res)
22 : PolyhedralProjection<Real>(xprim,xdual,bnd,con,mul,res),
23 DEFAULT_atol_ (std::sqrt(ROL_EPSILON<Real>()*std::sqrt(ROL_EPSILON<Real>()))),
24 DEFAULT_rtol_ (std::sqrt(ROL_EPSILON<Real>())),
25 DEFAULT_stol_ (std::sqrt(ROL_EPSILON<Real>())),
26 DEFAULT_decr_ (1e-4),
27 DEFAULT_factor_ (0.5),
28 DEFAULT_regscale_ (1e-4),
29 DEFAULT_errscale_ (1e-2),
30 DEFAULT_maxit_ (5000),
31 DEFAULT_lstype_ (0),
32 DEFAULT_verbosity_ (0),
33 DEFAULT_useproj_ (false),
34 atol_ (DEFAULT_atol_),
35 rtol_ (DEFAULT_rtol_),
36 stol_ (DEFAULT_stol_),
37 decr_ (DEFAULT_decr_),
38 factor_ (DEFAULT_factor_),
39 regscale_ (DEFAULT_regscale_),
40 errscale_ (DEFAULT_errscale_),
41 maxit_ (DEFAULT_maxit_),
42 lstype_ (DEFAULT_lstype_),
43 verbosity_ (DEFAULT_verbosity_),
44 useproj_ (DEFAULT_useproj_) {
45 dim_ = mul.dimension();
46 xnew_ = xprim.clone();
47 lnew_ = mul.clone();
48 dlam_ = mul.clone();
49
50 ParameterList list;
51 list.sublist("General").sublist("Krylov").set("Type", "Conjugate Gradients");
52 list.sublist("General").sublist("Krylov").set("Absolute Tolerance", 1e-6);
53 list.sublist("General").sublist("Krylov").set("Relative Tolerance", 1e-4);
54 list.sublist("General").sublist("Krylov").set("Iteration Limit", dim_);
55 list.sublist("General").set("Inexact Hessian-Times-A-Vector", false);
56 krylov_ = KrylovFactory<Real>(list);
57
59}
60
61template<typename Real>
63 const Vector<Real> &xdual,
64 const Ptr<BoundConstraint<Real>> &bnd,
65 const Ptr<Constraint<Real>> &con,
66 const Vector<Real> &mul,
67 const Vector<Real> &res,
68 ParameterList &list)
69 : PolyhedralProjection<Real>(xprim,xdual,bnd,con,mul,res),
70 DEFAULT_atol_ (std::sqrt(ROL_EPSILON<Real>()*std::sqrt(ROL_EPSILON<Real>()))),
71 DEFAULT_rtol_ (std::sqrt(ROL_EPSILON<Real>())),
72 DEFAULT_stol_ (std::sqrt(ROL_EPSILON<Real>())),
73 DEFAULT_decr_ (1e-4),
74 DEFAULT_factor_ (0.5),
75 DEFAULT_regscale_ (1e-4),
76 DEFAULT_errscale_ (1e-2),
77 DEFAULT_maxit_ (5000),
78 DEFAULT_lstype_ (0),
79 DEFAULT_verbosity_ (0),
80 DEFAULT_useproj_ (false),
81 atol_ (DEFAULT_atol_),
82 rtol_ (DEFAULT_rtol_),
83 stol_ (DEFAULT_stol_),
84 decr_ (DEFAULT_decr_),
85 factor_ (DEFAULT_factor_),
86 regscale_ (DEFAULT_regscale_),
87 errscale_ (DEFAULT_errscale_),
88 maxit_ (DEFAULT_maxit_),
89 lstype_ (DEFAULT_lstype_),
90 verbosity_ (DEFAULT_verbosity_),
91 useproj_ (DEFAULT_useproj_) {
92 dim_ = mul.dimension();
93 xnew_ = xprim.clone();
94 lnew_ = mul.clone();
95 dlam_ = mul.clone();
96 ParameterList &ppl = list.sublist("General").sublist("Polyhedral Projection");
97 atol_ = ppl.get("Absolute Tolerance", DEFAULT_atol_);
98 rtol_ = ppl.get("Relative Tolerance", DEFAULT_rtol_);
99 stol_ = ppl.sublist("Semismooth Newton").get("Step Tolerance", DEFAULT_stol_);
100 decr_ = ppl.sublist("Semismooth Newton").get("Sufficient Decrease Tolerance", DEFAULT_decr_);
101 factor_ = ppl.sublist("Semismooth Newton").get("Backtracking Rate", DEFAULT_factor_);
102 regscale_ = ppl.sublist("Semismooth Newton").get("Regularization Scale", DEFAULT_regscale_);
103 errscale_ = ppl.sublist("Semismooth Newton").get("Relative Error Scale", DEFAULT_errscale_);
104 maxit_ = ppl.get("Iteration Limit", DEFAULT_maxit_);
105 lstype_ = ppl.sublist("Semismooth Newton").get("Line Search Type", DEFAULT_lstype_);
106 verbosity_ = list.sublist("General").get("Output Level", DEFAULT_verbosity_);
107 useproj_ = ppl.sublist("Semismooth Newton").get("Project onto Separating Hyperplane", DEFAULT_useproj_);
108
109 ParameterList klist;
110
111 klist.sublist("General").sublist("Krylov") = ppl.sublist("Semismooth Newton").sublist("Krylov");
112 klist.sublist("General").set("Inexact Hessian-Times-A-Vector", false);
113 krylov_ = KrylovFactory<Real>(klist);
114
116}
117
118template<typename Real>
120 if (con_ == nullPtr) {
121 bnd_->project(x);
122 }
123 else {
124 project_ssn(x, *mul_, *dlam_, stream);
125 }
126}
127
128template<typename Real>
130 Real tol(std::sqrt(ROL_EPSILON<Real>()));
131 con_->update(y,UpdateType::Temp);
132 con_->value(r,y,tol);
133 return r.norm();
134}
135
136template<typename Real>
138 const Vector<Real> &r,
139 const Vector<Real> &y,
140 const Real mu,
141 const Real rho,
142 int &iter,
143 int &flag) const {
144 Ptr<Precond> M = makePtr<Precond>(mu);
145 Ptr<Jacobian> J = makePtr<Jacobian>(con_,bnd_,makePtrFromRef(y),xdual_,xprim_,mu);
146 krylov_->run(s,*J,r,*M,iter,flag);
147}
148
149template<typename Real>
151 const Vector<Real> &x,
152 const Vector<Real> &lam) const {
153 Real tol(std::sqrt(ROL_EPSILON<Real>()));
154 y.set(x);
155 con_->update(x,UpdateType::Temp);
156 con_->applyAdjointJacobian(*xdual_,lam,x,tol);
157 y.plus(xdual_->dual());
158 bnd_->project(y);
159}
160
161template<typename Real>
163 Vector<Real> &lam,
164 Vector<Real> &dlam,
165 std::ostream &stream) const {
166 const Real zero(0), half(0.5), one(1);
167 // Compute initial residual
168 update_primal(*xnew_,x,lam);
169 Real rnorm = residual(*res_,*xnew_);
170 if (rnorm == zero) {
171 x.set(*xnew_);
172 return;
173 }
174 Real alpha(1), tmp(0), mu(0), rho(1), dd(0);
175 int iter(0), flag(0);
176 std::ios_base::fmtflags streamFlags(stream.flags());
177 if (verbosity_ > 2) {
178 stream << std::endl;
179 stream << std::scientific << std::setprecision(6);
180 stream << " Polyhedral Projection using Dual Semismooth Newton" << std::endl;
181 stream << " ";
182 stream << std::setw(6) << std::left << "iter";
183 stream << std::setw(15) << std::left << "rnorm";
184 stream << std::setw(15) << std::left << "alpha";
185 stream << std::setw(15) << std::left << "mu";
186 stream << std::setw(15) << std::left << "rho";
187 stream << std::setw(15) << std::left << "rtol";
188 stream << std::setw(8) << std::left << "kiter";
189 stream << std::setw(8) << std::left << "kflag";
190 stream << std::endl;
191 }
192 for (int cnt = 0; cnt < maxit_; ++cnt) {
193 // Compute Newton step
194 mu = regscale_*std::max(rnorm,std::sqrt(rnorm));
195 rho = std::min(half,errscale_*std::min(std::sqrt(rnorm),rnorm));
196 solve_newton_system(dlam,*res_,*xnew_,mu,rho,iter,flag);
197 lnew_->set(lam); lnew_->axpy(-alpha, dlam);
198 update_primal(*xnew_,x,*lnew_);
199 // Perform line search
200 if (lstype_ == 1) { // Usual line search for nonlinear equations
201 tmp = residual(*res_,*xnew_);
202 while ( tmp > (one-decr_*alpha)*rnorm && alpha > stol_ ) {
203 alpha *= factor_;
204 lnew_->set(lam); lnew_->axpy(-alpha, dlam);
205 update_primal(*xnew_,x,*lnew_);
206 tmp = residual(*res_,*xnew_);
207 }
208 rnorm = tmp;
209 }
210 else { // Default Solodov and Svaiter line search
211 rnorm = residual(*res_,*xnew_);
212 //tmp = dlam.dot(res_->dual());
213 tmp = dlam.apply(*res_);
214 dd = dlam.dot(dlam);
215 while ( tmp < decr_*(one-rho)*mu*dd && alpha > stol_ ) {
216 alpha *= factor_;
217 lnew_->set(lam); lnew_->axpy(-alpha, dlam);
218 update_primal(*xnew_,x,*lnew_);
219 rnorm = residual(*res_,*xnew_);
220 //tmp = dlam.dot(res_->dual());
221 tmp = dlam.apply(*res_);
222 }
223 }
224 // Update iterate
225 lam.set(*lnew_);
226 // Project onto separating hyperplane
227 if (useproj_) {
228 lam.axpy(-alpha*tmp/(rnorm*rnorm),res_->dual());
229 update_primal(*xnew_,x,lam);
230 rnorm = residual(*res_,*xnew_);
231 }
232 if (verbosity_ > 2) {
233 stream << " ";
234 stream << std::setw(6) << std::left << cnt;
235 stream << std::setw(15) << std::left << rnorm;
236 stream << std::setw(15) << std::left << alpha;
237 stream << std::setw(15) << std::left << mu;
238 stream << std::setw(15) << std::left << rho;
239 stream << std::setw(15) << std::left << ctol_;
240 stream << std::setw(8) << std::left << iter;
241 stream << std::setw(8) << std::left << flag;
242 stream << std::endl;
243 }
244 if (rnorm <= ctol_) break;
245 alpha = one;
246 }
247 if (verbosity_ > 2) {
248 stream << std::endl;
249 }
250 if (rnorm > ctol_) {
251 //throw Exception::NotImplemented(">>> ROL::PolyhedralProjection::project : Projection failed!");
252 stream << ">>> ROL::PolyhedralProjection::project : Projection may be inaccurate! rnorm = ";
253 stream << rnorm << " rtol = " << ctol_ << std::endl;
254 }
255 x.set(*xnew_);
256 stream.flags(streamFlags);
257}
258
259template<typename Real>
261 // Set tolerance
262 Real resl = ROL_INF<Real>(), resu = ROL_INF<Real>();
263 if (bnd_->isLowerActivated()) resl = residual(*res_,*bnd_->getLowerBound());
264 if (bnd_->isUpperActivated()) resu = residual(*res_,*bnd_->getUpperBound());
265 Real res0 = std::max(resl,resu);
266 if (res0 < atol_) res0 = static_cast<Real>(1);
267 return std::min(atol_,rtol_*res0);
268}
269
270} // namespace ROL
271
272#endif
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
Provides the interface to apply upper and lower bound constraints.
Defines the general constraint operator interface.
void update_primal(Vector< Real > &y, const Vector< Real > &x, const Vector< Real > &lam) const
void solve_newton_system(Vector< Real > &s, const Vector< Real > &r, const Vector< Real > &y, const Real mu, const Real rho, int &iter, int &flag) const
void project_ssn(Vector< Real > &x, Vector< Real > &lam, Vector< Real > &dlam, std::ostream &stream=std::cout) const
SemismoothNewtonProjection(const Vector< Real > &xprim, const Vector< Real > &xdual, const Ptr< BoundConstraint< Real > > &bnd, const Ptr< Constraint< Real > > &con, const Vector< Real > &mul, const Vector< Real > &res)
void project(Vector< Real > &x, std::ostream &stream=std::cout) override
Real residual(Vector< Real > &r, const Vector< Real > &y) const
Defines the linear algebra or vector space interface.
virtual Real apply(const Vector< Real > &x) const
Apply to a dual vector. This is equivalent to the call .
virtual Real norm() const =0
Returns where .
virtual void set(const Vector &x)
Set where .
virtual void plus(const Vector &x)=0
Compute , 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 void axpy(const Real alpha, const Vector &x)
Compute where .
virtual Real dot(const Vector &x) const =0
Compute where .
Real ROL_EPSILON(void)
Platform-dependent machine epsilon.
Definition ROL_Types.hpp:57