ROL
ROL_TypeP_iPianoAlgorithm_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_TYPEP_IPIANOALGORITHM_DEF_HPP
11 #define ROL_TYPEP_IPIANOALGORITHM_DEF_HPP
12 
13 namespace ROL {
14 namespace TypeP {
15 
16 template<typename Real>
18  // Set status test
19  status_->reset();
20  status_->add(makePtr<StatusTest<Real>>(list));
21 
22  // Parse parameter list
23  ParameterList &lslist = list.sublist("Step").sublist("iPiano");
24  t0_ = list.sublist("Status Test").get("Gradient Scale", 1.0);
25  maxit_ = lslist.get("Reduction Iteration Limit", 20);
26  useConstBeta_ = lslist.get("Use Constant Beta", false);
27  beta_ = lslist.get("Momentum Parameter", 0.25);
28  rhodec_ = lslist.get("Backtracking Rate", 0.5);
29  rhoinc_ = lslist.get("Increase Rate", 2.0);
30  c1_ = lslist.get("Upper Interpolation Factor", 1e-5);
31  c2_ = lslist.get("Lower Interpolation Factor", 1e-6);
32  L_ = lslist.get("Initial Lipschitz Constant Estimate", 0.5/t0_);
33  initProx_ = lslist.get("Apply Prox to Initial Guess", false);
34  verbosity_ = list.sublist("General").get("Output Level", 0);
35  writeHeader_ = verbosity_ > 2;
36 }
37 
38 template<typename Real>
40  const Vector<Real> &g,
41  Objective<Real> &sobj,
42  Objective<Real> &nobj,
43  Vector<Real> &px,
44  Vector<Real> &dg,
45  std::ostream &outStream) {
46  Real ftol = std::sqrt(ROL_EPSILON<Real>());
47  // Initialize data
49  // Update approximate gradient and approximate objective function.
50  if (initProx_) {
51  nobj.prox(*state_->iterateVec,x,t0_,ftol); state_->nprox++;
52  x.set(*state_->iterateVec);
53  }
54  sobj.update(x,UpdateType::Initial,state_->iter);
55  state_->svalue = sobj.value(x,ftol); state_->nsval++;
56  nobj.update(x,UpdateType::Initial,state_->iter);
57  state_->nvalue = nobj.value(x,ftol); state_->nnval++;
58  state_->value = state_->svalue + state_->nvalue;
59  sobj.gradient(*state_->gradientVec,x,ftol); state_->ngrad++;
60  dg.set(state_->gradientVec->dual());
61  pgstep(*state_->iterateVec, *state_->stepVec, nobj, x, dg, t0_, ftol);
62  state_->snorm = state_->stepVec->norm();
63  state_->gnorm = state_->snorm / t0_;
64 }
65 
66 template<typename Real>
68  const Vector<Real> &g,
69  Objective<Real> &sobj,
70  Objective<Real> &nobj,
71  std::ostream &outStream ) {
72  const Real half(0.5), one(1), two(2);
73  // Initialize trust-region data
74  Ptr<Vector<Real>> sP = x.clone(), xP = x.clone(), dg = x.clone(), xold = x.clone();
75  initialize(x,g,sobj,nobj,*sP,*dg,outStream);
76  Real strial(0), strialP(0), snormP(0), LP(0), alphaP(0), betaP(0), gs(0), b(0);
77  Real tol(std::sqrt(ROL_EPSILON<Real>()));
78  bool accept(true);
79 
80  xold->set(x);
81 
82  // Output
83  if (verbosity_ > 0) writeOutput(outStream, true);
84 
85  // Iterate spectral projected gradient
86  while (status_->check(*state_)) {
87  // Compute parameters alpha and beta
88  if (!useConstBeta_) {
89  b = (c1_ + half * L_) / (c2_ + half * L_);
90  beta_ = (b - one) / (b - half);
91  }
92  alpha_ = two * (1 - beta_) / (two * c2_ + L_);
93  // Compute inertial step
94  state_->stepVec->set(x);
95  state_->stepVec->axpy(-alpha_, *dg);
96  state_->stepVec->axpy(beta_, x);
97  state_->stepVec->axpy(-beta_, *xold);
98  nobj.prox(*state_->iterateVec, *state_->stepVec, alpha_, tol); state_->nprox++;
99  state_->stepVec->set(*state_->iterateVec);
100  state_->stepVec->axpy(-one,x);
101  state_->snorm = state_->stepVec->norm();
102  // Compute smooth objective value
103  sobj.update(*state_->iterateVec,UpdateType::Trial);
104  nobj.update(*state_->iterateVec,UpdateType::Trial);
105  strial = sobj.value(*state_->iterateVec,tol); state_->nsval++;
106  gs = state_->gradientVec->apply(*state_->stepVec);
107  // Estimate Lipschitz constant of sobj
108  if (strial <= state_->svalue + gs + half * L_ * state_->snorm * state_->snorm) {
109  accept = true;
110  for (int i = 0; i < maxit_; ++i) {
111  // Store previously computed information
112  sobj.update(*state_->iterateVec,UpdateType::Accept);
113  nobj.update(*state_->iterateVec,UpdateType::Accept);
114  LP = L_;
115  alphaP = alpha_;
116  betaP = beta_;
117  strialP = strial;
118  snormP = state_->snorm;
119  xP->set(*state_->iterateVec);
120  sP->set(*state_->stepVec);
121  // Update alpha and beta with new Lipschitz constant estimate
122  L_ /= rhoinc_;
123  if (!useConstBeta_) {
124  b = (c1_ + half * L_) / (c2_ + half * L_);
125  beta_ = (b - one) / (b - half);
126  }
127  alpha_ = two * (one - beta_) / (two * c2_ + L_);
128  // Compute updated inertial step
129  state_->stepVec->set(x);
130  state_->stepVec->axpy(-alpha_, *dg);
131  state_->stepVec->axpy(beta_, x);
132  state_->stepVec->axpy(-beta_, *xold);
133  nobj.prox(*state_->iterateVec, *state_->stepVec, alpha_, tol); state_->nprox++;
134  state_->stepVec->set(*state_->iterateVec);
135  state_->stepVec->axpy(-one,x);
136  state_->snorm = state_->stepVec->norm();
137  // Compute smooth objective value
138  sobj.update(*state_->iterateVec,UpdateType::Trial);
139  strial = sobj.value(*state_->iterateVec,tol); state_->nsval++;
140  gs = state_->gradientVec->apply(*state_->stepVec);
141  if (strial > state_->svalue + gs + half * L_ * state_->snorm * state_->snorm) {
142  accept = false;
143  L_ = LP;
144  alpha_ = alphaP;
145  beta_ = betaP;
146  strial = strialP;
147  state_->snorm = snormP;
148  state_->iterateVec->set(*xP);
149  state_->stepVec->set(*sP);
150  break;
151  }
152  }
153  if (accept) {
154  sobj.update(*state_->iterateVec,UpdateType::Accept);
155  nobj.update(*state_->iterateVec,UpdateType::Accept);
156  }
157  else {
158  sobj.update(*state_->iterateVec,UpdateType::Revert);
159  nobj.update(*state_->iterateVec,UpdateType::Revert);
160  }
161  }
162  else {
163  while (strial > state_->svalue + gs + half * L_ * state_->snorm * state_->snorm) {
164  // Update alpha and beta with new Lipschitz constant estimate
165  L_ /= rhodec_;
166  if (!useConstBeta_) {
167  b = (c1_ + half * L_) / (c2_ + half * L_);
168  beta_ = (b - one) / (b - half);
169  }
170  alpha_ = two * (one - beta_) / (two * c2_ + L_);
171  // Compute updated inertial step
172  state_->stepVec->set(x);
173  state_->stepVec->axpy(-alpha_, *dg);
174  state_->stepVec->axpy(beta_, x);
175  state_->stepVec->axpy(-beta_, *xold);
176  nobj.prox(*state_->iterateVec, *state_->stepVec, alpha_, tol); state_->nprox++;
177  state_->stepVec->set(*state_->iterateVec);
178  state_->stepVec->axpy(-one,x);
179  state_->snorm = state_->stepVec->norm();
180  // Compute smooth objective value
181  sobj.update(*state_->iterateVec,UpdateType::Trial);
182  strial = sobj.value(*state_->iterateVec,tol); state_->nsval++;
183  gs = state_->gradientVec->apply(*state_->stepVec);
184  }
185  sobj.update(*state_->iterateVec,UpdateType::Accept);
186  nobj.update(*state_->iterateVec,UpdateType::Accept);
187  }
188  // Update iteration
189  state_->iter++;
190  xold->set(x);
191  x.set(*state_->iterateVec);
192  state_->svalue = strial;
193  state_->nvalue = nobj.value(x,tol); state_->nnval++;
194  state_->value = state_->svalue + state_->nvalue;
195  sobj.gradient(*state_->gradientVec,x,tol); state_->ngrad++;
196  dg->set(state_->gradientVec->dual());
197  // Compute proximal gradient for status check
198  pgstep(*xP,*sP,nobj,x,*dg,t0_,tol);
199  state_->gnorm = sP->norm() / t0_;
200 
201  // Update Output
202  if (verbosity_ > 0) writeOutput(outStream,writeHeader_);
203  }
204  if (verbosity_ > 0) TypeP::Algorithm<Real>::writeExitStatus(outStream);
205 }
206 
207 template<typename Real>
208 void iPianoAlgorithm<Real>::writeHeader( std::ostream& os ) const {
209  std::ios_base::fmtflags osFlags(os.flags());
210  if (verbosity_ > 1) {
211  os << std::string(109,'-') << std::endl;
212  os << "iPiano: Inertial proximal algorithm for nonconvex optimization";
213  os << " status output definitions" << std::endl << std::endl;
214  os << " iter - Number of iterates (steps taken)" << std::endl;
215  os << " value - Objective function value" << std::endl;
216  os << " gnorm - Norm of the proximal gradient with parameter lambda" << std::endl;
217  os << " snorm - Norm of the step (update to optimization vector)" << std::endl;
218  os << " alpha - Inertial gradient parameter" << std::endl;
219  os << " beta - Inertial step parameter" << std::endl;
220  os << " L - Lipschitz constant estimate" << std::endl;
221  os << " #sval - Cumulative number of times the smooth objective function was evaluated" << std::endl;
222  os << " #nval - Cumulative number of times the nonsmooth objective function was evaluated" << std::endl;
223  os << " #grad - Cumulative number of times the gradient was computed" << std::endl;
224  os << " #prox - Cumulative number of times the proximal operator was computed" << std::endl;
225  os << std::string(109,'-') << std::endl;
226  }
227 
228  os << " ";
229  os << std::setw(6) << std::left << "iter";
230  os << std::setw(15) << std::left << "value";
231  os << std::setw(15) << std::left << "gnorm";
232  os << std::setw(15) << std::left << "snorm";
233  os << std::setw(15) << std::left << "alpha";
234  os << std::setw(15) << std::left << "beta";
235  os << std::setw(15) << std::left << "L";
236  os << std::setw(10) << std::left << "#sval";
237  os << std::setw(10) << std::left << "#nval";
238  os << std::setw(10) << std::left << "#grad";
239  os << std::setw(10) << std::left << "#nprox";
240  os << std::endl;
241  os.flags(osFlags);
242 }
243 
244 template<typename Real>
245 void iPianoAlgorithm<Real>::writeName( std::ostream& os ) const {
246  std::ios_base::fmtflags osFlags(os.flags());
247  os << std::endl << "iPiano: Inertial Proximal Algorithm for Nonconvex Optimization (Type P)" << std::endl;
248  os.flags(osFlags);
249 }
250 
251 template<typename Real>
252 void iPianoAlgorithm<Real>::writeOutput( std::ostream& os, bool write_header ) const {
253  std::ios_base::fmtflags osFlags(os.flags());
254  os << std::scientific << std::setprecision(6);
255  if ( state_->iter == 0 ) writeName(os);
256  if ( write_header ) writeHeader(os);
257  if ( state_->iter == 0 ) {
258  os << " ";
259  os << std::setw(6) << std::left << state_->iter;
260  os << std::setw(15) << std::left << state_->value;
261  os << std::setw(15) << std::left << state_->gnorm;
262  os << std::setw(15) << std::left << "---";
263  os << std::setw(15) << std::left << "---";
264  os << std::setw(15) << std::left << "---";
265  os << std::setw(15) << std::left << L_;
266  os << std::setw(10) << std::left << state_->nsval;
267  os << std::setw(10) << std::left << state_->nnval;
268  os << std::setw(10) << std::left << state_->ngrad;
269  os << std::setw(10) << std::left << state_->nprox;
270  os << std::endl;
271  }
272  else {
273  os << " ";
274  os << std::setw(6) << std::left << state_->iter;
275  os << std::setw(15) << std::left << state_->value;
276  os << std::setw(15) << std::left << state_->gnorm;
277  os << std::setw(15) << std::left << state_->snorm;
278  os << std::setw(15) << std::left << alpha_;
279  os << std::setw(15) << std::left << beta_;
280  os << std::setw(15) << std::left << L_;
281  os << std::setw(10) << std::left << state_->nsval;
282  os << std::setw(10) << std::left << state_->nnval;
283  os << std::setw(10) << std::left << state_->ngrad;
284  os << std::setw(10) << std::left << state_->nprox;
285  os << std::endl;
286  }
287  os.flags(osFlags);
288 }
289 
290 } // namespace TypeP
291 } // namespace ROL
292 
293 #endif
Provides the interface to evaluate objective functions.
void initialize(Vector< Real > &x, const Vector< Real > &g, Objective< Real > &sobj, Objective< Real > &nobj, Vector< Real > &px, Vector< Real > &dg, std::ostream &outStream=std::cout)
virtual ROL::Ptr< Vector > clone() const =0
Clone to make a new (uninitialized) vector.
void writeName(std::ostream &os) const override
Print step name.
virtual Real value(const Vector< Real > &x, Real &tol)=0
Compute value.
virtual void prox(Vector< Real > &Pv, const Vector< Real > &v, Real t, Real &tol)
Compute the proximity operator.
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:46
virtual void update(const Vector< Real > &x, UpdateType type, int iter=-1)
Update objective function.
virtual void gradient(Vector< Real > &g, const Vector< Real > &x, Real &tol)
Compute gradient.
Provides an interface to check status of optimization algorithms.
void writeOutput(std::ostream &os, bool write_header=false) const override
Print iterate status.
void run(Vector< Real > &x, const Vector< Real > &g, Objective< Real > &sobj, Objective< Real > &nobj, std::ostream &outStream=std::cout) override
Run algorithm on unconstrained problems (Type-U). This general interface supports the use of dual opt...
virtual void set(const Vector &x)
Set where .
Definition: ROL_Vector.hpp:175
virtual void writeExitStatus(std::ostream &os) const
void initialize(const Vector< Real > &x, const Vector< Real > &g)
void writeHeader(std::ostream &os) const override
Print iterate header.