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 
13 namespace ROL {
14 
15 template<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 
61 template<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 
118 template<typename Real>
120  if (con_ == nullPtr) {
121  bnd_->project(x);
122  }
123  else {
124  project_ssn(x, *mul_, *dlam_, stream);
125  }
126 }
127 
128 template<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 
136 template<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 
149 template<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 
161 template<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 
259 template<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
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
virtual Real apply(const Vector< Real > &x) const
Apply to a dual vector. This is equivalent to the call .
Definition: ROL_Vector.hpp:204
void project(Vector< Real > &x, std::ostream &stream=std::cout) override
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 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
virtual void plus(const Vector &x)=0
Compute , where .
virtual void axpy(const Real alpha, const Vector &x)
Compute where .
Definition: ROL_Vector.hpp:119
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:46
virtual Real dot(const Vector &x) const =0
Compute where .
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
Provides the interface to apply upper and lower bound constraints.
Real residual(Vector< Real > &r, const Vector< Real > &y) const
void project_ssn(Vector< Real > &x, Vector< Real > &lam, Vector< Real > &dlam, std::ostream &stream=std::cout) const
virtual void set(const Vector &x)
Set where .
Definition: ROL_Vector.hpp:175
virtual Real norm() const =0
Returns where .
Real ROL_EPSILON(void)
Platform-dependent machine epsilon.
Definition: ROL_Types.hpp:57
void update_primal(Vector< Real > &y, const Vector< Real > &x, const Vector< Real > &lam) const
Defines the general constraint operator interface.