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
13namespace ROL {
14namespace TypeP {
15
16template<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);
36}
37
38template<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
66template<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 }
205}
206
207template<typename Real>
208void 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
244template<typename Real>
245void 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
251template<typename Real>
252void 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
virtual void initialize(const Vector< Real > &x)
Initialize temporary variables.
Provides the interface to evaluate objective functions.
virtual void prox(Vector< Real > &Pv, const Vector< Real > &v, Real t, Real &tol)
Compute the proximity operator.
virtual void gradient(Vector< Real > &g, const Vector< Real > &x, Real &tol)
Compute gradient.
virtual Real value(const Vector< Real > &x, Real &tol)=0
Compute value.
virtual void update(const Vector< Real > &x, UpdateType type, int iter=-1)
Update objective function.
Provides an interface to check status of optimization algorithms.
void pgstep(Vector< Real > &pgiter, Vector< Real > &pgstep, Objective< Real > &nobj, const Vector< Real > &x, const Vector< Real > &dg, Real t, Real &tol) const
const Ptr< AlgorithmState< Real > > state_
virtual void writeExitStatus(std::ostream &os) const
const Ptr< CombinedStatusTest< Real > > status_
void initialize(const Vector< Real > &x, const Vector< Real > &g)
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...
void writeName(std::ostream &os) const override
Print step name.
void writeHeader(std::ostream &os) const override
Print iterate header.
void writeOutput(std::ostream &os, bool write_header=false) const override
Print iterate status.
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)
Defines the linear algebra or vector space interface.
virtual void set(const Vector &x)
Set where .
virtual ROL::Ptr< Vector > clone() const =0
Clone to make a new (uninitialized) vector.
Real ROL_EPSILON(void)
Platform-dependent machine epsilon.
Definition ROL_Types.hpp:57