ROL
ROL_InteriorPointPenalty.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_INTERIORPOINTPENALTY_H
11#define ROL_INTERIORPOINTPENALTY_H
12
13#include "ROL_Objective.hpp"
15#include "ROL_ParameterList.hpp"
16
26namespace ROL {
27
28template<class Real>
29class InteriorPointPenalty : public Objective<Real> {
30
31 typedef Vector<Real> V;
34
35 typedef Elementwise::ValueSet<Real> ValueSet;
36
37private:
38
39 const ROL::Ptr<OBJ> obj_;
40 const ROL::Ptr<BND> bnd_;
41 const ROL::Ptr<const V> lo_;
42 const ROL::Ptr<const V> up_;
43
44 ROL::Ptr<V> g_; // Gradient of penalized objective
45
46 ROL::Ptr<V> maskL_; // Elements are 1 when xl>-INF, zero for xl = -INF
47 ROL::Ptr<V> maskU_; // Elements are 1 when xu< INF, zero for xu = INF
48
49 ROL::Ptr<V> a_; // Scratch vector
50 ROL::Ptr<V> b_; // Scratch vector
51 ROL::Ptr<V> c_; // Scratch vector
52
53 bool useLinearDamping_; // Add linear damping terms to the penalized objective
54 // to prevent the problems such as when the log barrier
55 // contribution is unbounded below on the feasible set
56
57 Real mu_; // Penalty parameter
58 Real kappaD_; // Linear damping coefficient
59 Real fval_; // Unpenalized objective value
60
61 int nfval_;
62 int ngval_;
63
64
65
66 // x <- f(x) = { log(x) if x > 0
67 // { 0 if x <= 0
68 class ModifiedLogarithm : public Elementwise::UnaryFunction<Real> {
69 public:
70 Real apply( const Real &x ) const {
71 return (x>0) ? std::log(x) : Real(0.0);
72 }
73 }; // class ModifiedLogarithm
74
75 // x <- f(x) = { 1/x if x > 0
76 // { 0 if x <= 0
77 class ModifiedReciprocal : public Elementwise::UnaryFunction<Real> {
78 public:
79 Real apply( const Real &x ) const {
80 return (x>0) ? 1.0/x : Real(0.0);
81 }
82
83 }; // class ModifiedReciprocal
84
85 // x <- f(x,y) = { y/x if x > 0
86 // { 0 if x <= 0
87 class ModifiedDivide : public Elementwise::BinaryFunction<Real> {
88 public:
89 Real apply( const Real &x, const Real &y ) const {
90 return (x>0) ? y/x : Real(0.0);
91 }
92 }; // class ModifiedDivide
93
94 // x <- f(x,y) = { x if y != 0, complement == false
95 // { 0 if y == 0, complement == false
96 // { 0 if y != 0, complement == true
97 // { x if y == 0, complement == true
98 class Mask : public Elementwise::BinaryFunction<Real> {
99 private:
101 public:
102 Mask( bool complement ) : complement_(complement) {}
103 Real apply( const Real &x, const Real &y ) const {
104 return ( complement_ ^ (y !=0) ) ? 0 : x;
105 }
106 }; // class Mask
107
108
109public:
110
112
113 InteriorPointPenalty( const ROL::Ptr<Objective<Real> > &obj,
114 const ROL::Ptr<BoundConstraint<Real> > &con,
115 ROL::ParameterList &parlist ) :
116 obj_(obj), bnd_(con), lo_( con->getLowerBound() ), up_( con->getUpperBound() ) {
117
118 Real one(1);
119 Real zero(0);
120
121 // Determine the index sets where the
122 ValueSet isBoundedBelow( ROL_NINF<Real>(), ValueSet::GREATER_THAN, one, zero );
123 ValueSet isBoundedAbove( ROL_INF<Real>(), ValueSet::LESS_THAN, one, zero );
124
125 maskL_ = lo_->clone();
126 maskU_ = up_->clone();
127
128 maskL_->applyBinary(isBoundedBelow,*lo_);
129 maskU_->applyBinary(isBoundedAbove,*up_);
130
131 ROL::ParameterList &iplist = parlist.sublist("Step").sublist("Primal Dual Interior Point");
132 ROL::ParameterList &lblist = iplist.sublist("Barrier Objective");
133
134 useLinearDamping_ = lblist.get("Use Linear Damping",true);
135 kappaD_ = lblist.get("Linear Damping Coefficient",1.e-4);
136 mu_ = lblist.get("Initial Barrier Parameter",0.1);
137
138
139 a_ = lo_->clone();
140 b_ = up_->clone();
141 g_ = lo_->dual().clone();
142
143 if( useLinearDamping_ ) {
144 c_ = lo_->clone();
145 }
146 }
147
148 Real getObjectiveValue(void) const {
149 return fval_;
150 }
151
152 ROL::Ptr<Vector<Real> > getGradient(void) const {
153 return g_;
154 }
155
157 return nfval_;
158 }
159
161 return ngval_;
162 }
163
164 ROL::Ptr<const Vector<Real> > getLowerMask(void) const {
165 return maskL_;
166 }
167
168 ROL::Ptr<const Vector<Real> > getUpperMask(void) const {
169 return maskU_;
170 }
171
179 void update( const Vector<Real> &x, bool flag = true, int iter = -1 ) {
180 obj_->update(x,flag,iter);
181 }
182
194 Real value( const Vector<Real> &x, Real &tol ) {
195
197 Elementwise::ReductionSum<Real> sum;
198 Elementwise::Multiply<Real> mult;
199
200 // Compute the unpenalized objective value
201 fval_ = obj_->value(x,tol);
202 nfval_++;
203
204 Real fval = fval_;
205 Real linearTerm = 0.0; // Linear damping contribution
206
207 a_->set(x); // a_i = x_i
208 a_->axpy(-1.0,*lo_); // a_i = x_i-l_i
209
210 if( useLinearDamping_ ) {
211
212 c_->set(*maskL_); // c_i = { 1 if l_i > NINF
213 // { 0 otherwise
214 c_->applyBinary(Mask(true),*maskU_); // c_i = { 1 if l_i > NINF and u_i = INF
215 // { 0 otherwise
216 c_->applyBinary(mult,*a_); // c_i = { x_i-l_i if l_i > NINF and u_i = INF
217
218 // Penalizes large positive x_i when only a lower bound exists
219 linearTerm += c_->reduce(sum);
220 }
221
222 a_->applyUnary(mlog); // a_i = mlog(x_i-l_i)
223
224 Real aval = a_->dot(*maskL_);
225
226 b_->set(*up_); // b_i = u_i
227 b_->axpy(-1.0,x); // b_i = u_i-x_i
228
229 if( useLinearDamping_ ) {
230
231 c_->set(*maskU_); // c_i = { 1 if u_i < INF
232 // { 0 otherwise
233 c_->applyBinary(Mask(true),*maskL_); // c_i = { 1 if u_i < INF and l_i = NINF
234 // { 0 otherwise
235 c_->applyBinary(mult,*b_); // c_i = { u_i-x_i if u_i < INF and l_i = NINF
236 // { 0 otherwise
237
238 // Penalizes large negative x_i when only an upper bound exists
239 linearTerm += c_->reduce(sum);
240
241 }
242
243 b_->applyUnary(mlog); // b_i = mlog(u_i-x_i)
244
245 Real bval = b_->dot(*maskU_);
246
247
248 fval -= mu_*(aval+bval);
249 fval += kappaD_*mu_*linearTerm;
250
251 return fval;
252
253 }
254
263 void gradient( Vector<Real> &g, const Vector<Real> &x, Real &tol ) {
264 // Compute gradient of objective function
265 obj_->gradient(*g_,x,tol);
266 ngval_++;
267 g.set(*g_);
268
269 // Add gradient of the log barrier penalty
271
272 a_->set(x); // a = x
273 a_->axpy(-1.0,*lo_); // a = x-l
274
275 a_->applyUnary(mrec); // a_i = 1/(x_i-l_i) for i s.t. x_i > l_i, 0 otherwise
276 a_->applyBinary(Mask(true),*maskL_); // zero elements where l = NINF
277
278 b_->set(*up_); // b = u
279 b_->axpy(-1.0,x); // b = u-x
280 b_->applyUnary(mrec); // b_i = 1/(u_i-x_i) for i s.t. u_i > x_i, 0 otherwise
281 b_->applyBinary(Mask(true),*maskU_); // zero elements where u = INF
282
283 g.axpy(-mu_,*a_);
284 g.axpy(mu_,*b_);
285
286 if( useLinearDamping_ ) {
287
288 a_->set(*maskL_);
289 a_->applyBinary(Mask(true),*maskU_); // a_i = { 1 if l_i > NINF and u_i = INF
290 // { 0 otherwise
291 b_->set(*maskU_);
292 b_->applyBinary(Mask(true),*maskL_); // b_i = { 1 if u_i < INF and l_i = NINF
293 // { 0 otherwise
294 g.axpy(-mu_*kappaD_,*a_);
295 g.axpy( mu_*kappaD_,*b_);
296
297 }
298 }
299
309 void hessVec( Vector<Real> &hv, const Vector<Real> &v, const Vector<Real> &x, Real &tol ) {
310
312 Elementwise::Multiply<Real> mult;
313 Elementwise::Power<Real> square(2.0);
314
315 obj_->hessVec(hv,v,x,tol);
316
317 a_->set(x); // a = x
318 a_->axpy(-1.0,*lo_); // a = x-l
319 a_->applyUnary(mrec); // a_i = 1/(x_i-l_i) for i s.t. x_i > l_i, 0 otherwise
320 a_->applyBinary(Mask(true),*maskL_); // zero elements where l = NINF
321 a_->applyUnary(square); // a_i = { (x_i-l_i)^(-2) if l_i > NINF
322 // { 0 if l_i = NINF
323 a_->applyBinary(mult,v);
324
325 b_->set(*up_); // b = u
326 b_->axpy(-1.0,x); // b = u-x
327 b_->applyUnary(mrec); // b_i = 1/(u_i-x_i) for i s.t. u_i > x_i, 0 otherwise
328 b_->applyBinary(Mask(true),*maskU_); // zero elements where u = INF
329 b_->applyUnary(square); // b_i = { (u_i-x_i)^(-2) if u_i < INF
330 // { 0 if u_i = INF
331 b_->applyBinary(mult,v);
332
333 hv.axpy(mu_,*a_);
334 hv.axpy(mu_,*b_);
335 }
336
337 // Return the unpenalized objective
338 const ROL::Ptr<OBJ> getObjective( void ) { return obj_; }
339
340 // Return the bound constraint
341 const ROL::Ptr<BND> getBoundConstraint( void ) { return bnd_; }
342
343}; // class InteriorPointPenalty
344
345}
346
347
348#endif // ROL_INTERIORPOINTPENALTY_H
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
Provides the interface to apply upper and lower bound constraints.
Real apply(const Real &x, const Real &y) const
Real apply(const Real &x, const Real &y) const
Provides the interface to evaluate the Interior Pointy log barrier penalty function with upper and lo...
Elementwise::ValueSet< Real > ValueSet
void update(const Vector< Real > &x, bool flag=true, int iter=-1)
Update the interior point penalized objective.
InteriorPointPenalty(const ROL::Ptr< Objective< Real > > &obj, const ROL::Ptr< BoundConstraint< Real > > &con, ROL::ParameterList &parlist)
ROL::Ptr< Vector< Real > > getGradient(void) const
void gradient(Vector< Real > &g, const Vector< Real > &x, Real &tol)
Compute gradient.
const ROL::Ptr< OBJ > getObjective(void)
ROL::Ptr< const Vector< Real > > getUpperMask(void) const
const ROL::Ptr< BND > getBoundConstraint(void)
void hessVec(Vector< Real > &hv, const Vector< Real > &v, const Vector< Real > &x, Real &tol)
Compute action of Hessian on vector.
ROL::Ptr< const Vector< Real > > getLowerMask(void) const
Real value(const Vector< Real > &x, Real &tol)
Compute value.
Provides the interface to evaluate objective functions.
Defines the linear algebra or vector space interface.
virtual void set(const Vector &x)
Set where .
virtual void axpy(const Real alpha, const Vector &x)
Compute where .