ROL
ROL_InteriorPointPenalty.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ************************************************************************
3 //
4 // Rapid Optimization Library (ROL) Package
5 // Copyright (2014) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact lead developers:
38 // Drew Kouri (dpkouri@sandia.gov) and
39 // Denis Ridzal (dridzal@sandia.gov)
40 //
41 // ************************************************************************
42 // @HEADER
43 
44 #ifndef ROL_INTERIORPOINTPENALTY_H
45 #define ROL_INTERIORPOINTPENALTY_H
46 
47 #include "ROL_Objective.hpp"
48 #include "ROL_BoundConstraint.hpp"
49 #include "ROL_ParameterList.hpp"
50 
60 namespace ROL {
61 
62 template<class Real>
63 class InteriorPointPenalty : public Objective<Real> {
64 
65  typedef Vector<Real> V;
68 
69  typedef Elementwise::ValueSet<Real> ValueSet;
70 
71 private:
72 
73  const ROL::Ptr<OBJ> obj_;
74  const ROL::Ptr<BND> bnd_;
75  const ROL::Ptr<const V> lo_;
76  const ROL::Ptr<const V> up_;
77 
78  ROL::Ptr<V> g_; // Gradient of penalized objective
79 
80  ROL::Ptr<V> maskL_; // Elements are 1 when xl>-INF, zero for xl = -INF
81  ROL::Ptr<V> maskU_; // Elements are 1 when xu< INF, zero for xu = INF
82 
83  ROL::Ptr<V> a_; // Scratch vector
84  ROL::Ptr<V> b_; // Scratch vector
85  ROL::Ptr<V> c_; // Scratch vector
86 
87  bool useLinearDamping_; // Add linear damping terms to the penalized objective
88  // to prevent the problems such as when the log barrier
89  // contribution is unbounded below on the feasible set
90 
91  Real mu_; // Penalty parameter
92  Real kappaD_; // Linear damping coefficient
93  Real fval_; // Unpenalized objective value
94 
95  int nfval_;
96  int ngval_;
97 
98 
99 
100  // x <- f(x) = { log(x) if x > 0
101  // { 0 if x <= 0
102  class ModifiedLogarithm : public Elementwise::UnaryFunction<Real> {
103  public:
104  Real apply( const Real &x ) const {
105  return (x>0) ? std::log(x) : Real(0.0);
106  }
107  }; // class ModifiedLogarithm
108 
109  // x <- f(x) = { 1/x if x > 0
110  // { 0 if x <= 0
111  class ModifiedReciprocal : public Elementwise::UnaryFunction<Real> {
112  public:
113  Real apply( const Real &x ) const {
114  return (x>0) ? 1.0/x : Real(0.0);
115  }
116 
117  }; // class ModifiedReciprocal
118 
119  // x <- f(x,y) = { y/x if x > 0
120  // { 0 if x <= 0
121  class ModifiedDivide : public Elementwise::BinaryFunction<Real> {
122  public:
123  Real apply( const Real &x, const Real &y ) const {
124  return (x>0) ? y/x : Real(0.0);
125  }
126  }; // class ModifiedDivide
127 
128  // x <- f(x,y) = { x if y != 0, complement == false
129  // { 0 if y == 0, complement == false
130  // { 0 if y != 0, complement == true
131  // { x if y == 0, complement == true
132  class Mask : public Elementwise::BinaryFunction<Real> {
133  private:
135  public:
136  Mask( bool complement ) : complement_(complement) {}
137  Real apply( const Real &x, const Real &y ) const {
138  return ( complement_ ^ (y !=0) ) ? 0 : x;
139  }
140  }; // class Mask
141 
142 
143 public:
144 
146 
147  InteriorPointPenalty( const ROL::Ptr<Objective<Real> > &obj,
148  const ROL::Ptr<BoundConstraint<Real> > &con,
149  ROL::ParameterList &parlist ) :
150  obj_(obj), bnd_(con), lo_( con->getLowerBound() ), up_( con->getUpperBound() ) {
151 
152  Real one(1);
153  Real zero(0);
154 
155  // Determine the index sets where the
156  ValueSet isBoundedBelow( ROL_NINF<Real>(), ValueSet::GREATER_THAN, one, zero );
157  ValueSet isBoundedAbove( ROL_INF<Real>(), ValueSet::LESS_THAN, one, zero );
158 
159  maskL_ = lo_->clone();
160  maskU_ = up_->clone();
161 
162  maskL_->applyBinary(isBoundedBelow,*lo_);
163  maskU_->applyBinary(isBoundedAbove,*up_);
164 
165  ROL::ParameterList &iplist = parlist.sublist("Step").sublist("Primal Dual Interior Point");
166  ROL::ParameterList &lblist = iplist.sublist("Barrier Objective");
167 
168  useLinearDamping_ = lblist.get("Use Linear Damping",true);
169  kappaD_ = lblist.get("Linear Damping Coefficient",1.e-4);
170  mu_ = lblist.get("Initial Barrier Parameter",0.1);
171 
172 
173  a_ = lo_->clone();
174  b_ = up_->clone();
175  g_ = lo_->dual().clone();
176 
177  if( useLinearDamping_ ) {
178  c_ = lo_->clone();
179  }
180  }
181 
182  Real getObjectiveValue(void) const {
183  return fval_;
184  }
185 
186  ROL::Ptr<Vector<Real> > getGradient(void) const {
187  return g_;
188  }
189 
191  return nfval_;
192  }
193 
195  return ngval_;
196  }
197 
198  ROL::Ptr<const Vector<Real> > getLowerMask(void) const {
199  return maskL_;
200  }
201 
202  ROL::Ptr<const Vector<Real> > getUpperMask(void) const {
203  return maskU_;
204  }
205 
213  void update( const Vector<Real> &x, bool flag = true, int iter = -1 ) {
214  obj_->update(x,flag,iter);
215  bnd_->update(x,flag,iter);
216  }
217 
229  Real value( const Vector<Real> &x, Real &tol ) {
230 
231  ModifiedLogarithm mlog;
232  Elementwise::ReductionSum<Real> sum;
233  Elementwise::Multiply<Real> mult;
234 
235  // Compute the unpenalized objective value
236  fval_ = obj_->value(x,tol);
237  nfval_++;
238 
239  Real fval = fval_;
240  Real linearTerm = 0.0; // Linear damping contribution
241 
242  a_->set(x); // a_i = x_i
243  a_->axpy(-1.0,*lo_); // a_i = x_i-l_i
244 
245  if( useLinearDamping_ ) {
246 
247  c_->set(*maskL_); // c_i = { 1 if l_i > NINF
248  // { 0 otherwise
249  c_->applyBinary(Mask(true),*maskU_); // c_i = { 1 if l_i > NINF and u_i = INF
250  // { 0 otherwise
251  c_->applyBinary(mult,*a_); // c_i = { x_i-l_i if l_i > NINF and u_i = INF
252 
253  // Penalizes large positive x_i when only a lower bound exists
254  linearTerm += c_->reduce(sum);
255  }
256 
257  a_->applyUnary(mlog); // a_i = mlog(x_i-l_i)
258 
259  Real aval = a_->dot(*maskL_);
260 
261  b_->set(*up_); // b_i = u_i
262  b_->axpy(-1.0,x); // b_i = u_i-x_i
263 
264  if( useLinearDamping_ ) {
265 
266  c_->set(*maskU_); // c_i = { 1 if u_i < INF
267  // { 0 otherwise
268  c_->applyBinary(Mask(true),*maskL_); // c_i = { 1 if u_i < INF and l_i = NINF
269  // { 0 otherwise
270  c_->applyBinary(mult,*b_); // c_i = { u_i-x_i if u_i < INF and l_i = NINF
271  // { 0 otherwise
272 
273  // Penalizes large negative x_i when only an upper bound exists
274  linearTerm += c_->reduce(sum);
275 
276  }
277 
278  b_->applyUnary(mlog); // b_i = mlog(u_i-x_i)
279 
280  Real bval = b_->dot(*maskU_);
281 
282 
283  fval -= mu_*(aval+bval);
284  fval += kappaD_*mu_*linearTerm;
285 
286  return fval;
287 
288  }
289 
298  void gradient( Vector<Real> &g, const Vector<Real> &x, Real &tol ) {
299  // Compute gradient of objective function
300  obj_->gradient(*g_,x,tol);
301  ngval_++;
302  g.set(*g_);
303 
304  // Add gradient of the log barrier penalty
305  ModifiedReciprocal mrec;
306 
307  a_->set(x); // a = x
308  a_->axpy(-1.0,*lo_); // a = x-l
309 
310  a_->applyUnary(mrec); // a_i = 1/(x_i-l_i) for i s.t. x_i > l_i, 0 otherwise
311  a_->applyBinary(Mask(true),*maskL_); // zero elements where l = NINF
312 
313  b_->set(*up_); // b = u
314  b_->axpy(-1.0,x); // b = u-x
315  b_->applyUnary(mrec); // b_i = 1/(u_i-x_i) for i s.t. u_i > x_i, 0 otherwise
316  b_->applyBinary(Mask(true),*maskU_); // zero elements where u = INF
317 
318  g.axpy(-mu_,*a_);
319  g.axpy(mu_,*b_);
320 
321  if( useLinearDamping_ ) {
322 
323  a_->set(*maskL_);
324  a_->applyBinary(Mask(true),*maskU_); // a_i = { 1 if l_i > NINF and u_i = INF
325  // { 0 otherwise
326  b_->set(*maskU_);
327  b_->applyBinary(Mask(true),*maskL_); // b_i = { 1 if u_i < INF and l_i = NINF
328  // { 0 otherwise
329  g.axpy(-mu_*kappaD_,*a_);
330  g.axpy( mu_*kappaD_,*b_);
331 
332  }
333  }
334 
344  void hessVec( Vector<Real> &hv, const Vector<Real> &v, const Vector<Real> &x, Real &tol ) {
345 
346  ModifiedReciprocal mrec;
347  Elementwise::Multiply<Real> mult;
348  Elementwise::Power<Real> square(2.0);
349 
350  obj_->hessVec(hv,v,x,tol);
351 
352  a_->set(x); // a = x
353  a_->axpy(-1.0,*lo_); // a = x-l
354  a_->applyUnary(mrec); // a_i = 1/(x_i-l_i) for i s.t. x_i > l_i, 0 otherwise
355  a_->applyBinary(Mask(true),*maskL_); // zero elements where l = NINF
356  a_->applyUnary(square); // a_i = { (x_i-l_i)^(-2) if l_i > NINF
357  // { 0 if l_i = NINF
358  a_->applyBinary(mult,v);
359 
360  b_->set(*up_); // b = u
361  b_->axpy(-1.0,x); // b = u-x
362  b_->applyUnary(mrec); // b_i = 1/(u_i-x_i) for i s.t. u_i > x_i, 0 otherwise
363  b_->applyBinary(Mask(true),*maskU_); // zero elements where u = INF
364  b_->applyUnary(square); // b_i = { (u_i-x_i)^(-2) if u_i < INF
365  // { 0 if u_i = INF
366  b_->applyBinary(mult,v);
367 
368  hv.axpy(mu_,*a_);
369  hv.axpy(mu_,*b_);
370  }
371 
372  // Return the unpenalized objective
373  const ROL::Ptr<OBJ> getObjective( void ) { return obj_; }
374 
375  // Return the bound constraint
376  const ROL::Ptr<BND> getBoundConstraint( void ) { return bnd_; }
377 
378 }; // class InteriorPointPenalty
379 
380 }
381 
382 
383 #endif // ROL_INTERIORPOINTPENALTY_H
Provides the interface to evaluate objective functions.
Real value(const Vector< Real > &x, Real &tol)
Compute value.
void update(const Vector< Real > &x, bool flag=true, int iter=-1)
Update the interior point penalized objective.
virtual void axpy(const Real alpha, const Vector &x)
Compute where .
Definition: ROL_Vector.hpp:153
ROL::Ptr< const Vector< Real > > getLowerMask(void) const
ROL::Ptr< const Vector< Real > > getUpperMask(void) const
InteriorPointPenalty(const ROL::Ptr< Objective< Real > > &obj, const ROL::Ptr< BoundConstraint< Real > > &con, ROL::ParameterList &parlist)
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:80
Real apply(const Real &x, const Real &y) const
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
const ROL::Ptr< OBJ > getObjective(void)
void hessVec(Vector< Real > &hv, const Vector< Real > &v, const Vector< Real > &x, Real &tol)
Compute action of Hessian on vector.
Provides the interface to evaluate the Interior Pointy log barrier penalty function with upper and lo...
const ROL::Ptr< BND > getBoundConstraint(void)
ROL::Ptr< Vector< Real > > getGradient(void) const
Real apply(const Real &x, const Real &y) const
const ROL::Ptr< const V > lo_
const ROL::Ptr< const V > up_
void gradient(Vector< Real > &g, const Vector< Real > &x, Real &tol)
Compute gradient.
Provides the interface to apply upper and lower bound constraints.
virtual void set(const Vector &x)
Set where .
Definition: ROL_Vector.hpp:209
Elementwise::ValueSet< Real > ValueSet