ROL
ROL_MoreauYosidaObjective.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_MOREAUYOSIDAOBJECTIVE_H
45 #define ROL_MOREAUYOSIDAOBJECTIVE_H
46 
47 #include "ROL_Objective.hpp"
48 #include "ROL_BoundConstraint.hpp"
49 #include "ROL_Vector.hpp"
50 #include "ROL_Types.hpp"
51 #include "ROL_Ptr.hpp"
52 #include "ROL_ScalarController.hpp"
53 #include "ROL_ParameterList.hpp"
54 #include <iostream>
55 
64 namespace ROL {
65 
66 template <class Real>
67 class MoreauYosidaObjective : public Objective<Real> {
68 private:
69  const Ptr<Objective<Real>> obj_;
70  const Ptr<BoundConstraint<Real>> bnd_;
71 
72  Ptr<Vector<Real>> l_;
73  Ptr<Vector<Real>> u_;
74  Ptr<Vector<Real>> l1_;
75  Ptr<Vector<Real>> u1_;
76  Ptr<Vector<Real>> dl1_;
77  Ptr<Vector<Real>> du1_;
78  Ptr<Vector<Real>> xlam_;
79  Ptr<Vector<Real>> v_;
80  Ptr<Vector<Real>> dv_;
81  Ptr<Vector<Real>> dv2_;
82  Ptr<Vector<Real>> lam_;
83  Ptr<Vector<Real>> tmp_;
84 
85  Ptr<ScalarController<Real,int>> fval_;
86  Ptr<VectorController<Real,int>> gradient_;
87 
88  Real mu_;
90  int nfval_;
91  int ngrad_;
94 
95  void computePenalty(const Vector<Real> &x) {
96  if ( bnd_->isActivated() ) {
97  Real one = 1.0;
98  if ( !isPenEvaluated_ ) {
99  xlam_->set(x);
100  xlam_->axpy(one/mu_,*lam_);
101 
102  if ( bnd_->isFeasible(*xlam_) ) {
103  l1_->zero(); dl1_->zero();
104  u1_->zero(); du1_->zero();
105  }
106  else {
107  // Compute lower penalty component
108  l1_->set(*l_);
109  bnd_->pruneLowerInactive(*l1_,*xlam_);
110  tmp_->set(*xlam_);
111  bnd_->pruneLowerInactive(*tmp_,*xlam_);
112  l1_->axpy(-one,*tmp_);
113 
114  // Compute upper penalty component
115  u1_->set(*xlam_);
116  bnd_->pruneUpperInactive(*u1_,*xlam_);
117  tmp_->set(*u_);
118  bnd_->pruneUpperInactive(*tmp_,*xlam_);
119  u1_->axpy(-one,*tmp_);
120 
121  // Compute derivative of lower penalty component
122  dl1_->set(l1_->dual());
123  bnd_->pruneLowerInactive(*dl1_,*xlam_);
124 
125  // Compute derivative of upper penalty component
126  du1_->set(u1_->dual());
127  bnd_->pruneUpperInactive(*du1_,*xlam_);
128  }
129 
130  isPenEvaluated_ = true;
131  }
132  }
133  }
134 
135  void initialize(const Vector<Real> &x,
136  const Vector<Real> &g) {
137  fval_ = makePtr<ScalarController<Real,int>>();
138  gradient_ = makePtr<VectorController<Real,int>>();
139 
140  l_ = x.clone();
141  l1_ = x.clone();
142  dl1_ = g.clone();
143  u_ = x.clone();
144  u1_ = x.clone();
145  du1_ = g.clone();
146  xlam_ = x.clone();
147  v_ = x.clone();
148  dv_ = g.clone();
149  dv2_ = g.clone();
150  lam_ = x.clone();
151  tmp_ = x.clone();
152 
153  l_->set(*bnd_->getLowerBound());
154  u_->set(*bnd_->getUpperBound());
155 
156  lam_->zero();
157  //lam_->set(*u_);
158  //lam_->plus(*l_);
159  //lam_->scale(0.5);
160  }
161 
162 public:
164  const Ptr<BoundConstraint<Real>> &bnd,
165  const Vector<Real> &x,
166  const Vector<Real> &g,
167  const Real mu = 1e1,
168  const bool updateMultiplier = true,
169  const bool updatePenalty = true)
170  : obj_(obj), bnd_(bnd), mu_(mu),
171  isPenEvaluated_(false), nfval_(0), ngrad_(0),
172  updateMultiplier_(updateMultiplier), updatePenalty_(updatePenalty) {
173  initialize(x,g);
174  }
175 
177  const Ptr<BoundConstraint<Real>> &bnd,
178  const Vector<Real> &x,
179  const Vector<Real> &g,
180  const Vector<Real> &lam,
181  const Real mu = 1e1,
182  const bool updateMultiplier = true,
183  const bool updatePenalty = true)
184  : MoreauYosidaObjective(obj,bnd,x,g,mu,updateMultiplier,updatePenalty) {
185  lam_->set(lam);
186  }
187 
189  const Ptr<BoundConstraint<Real>> &bnd,
190  const Vector<Real> &x,
191  const Vector<Real> &g,
192  ParameterList &parlist)
193  : obj_(obj), bnd_(bnd),
194  isPenEvaluated_(false), nfval_(0), ngrad_(0) {
195  initialize(x,g);
196  ParameterList &list = parlist.sublist("Step").sublist("Moreau-Yosida Penalty");
197  updateMultiplier_ = list.get("Update Multiplier",true);
198  updatePenalty_ = list.get("Update Penalty",true);
199  mu_ = list.get("Initial Penalty Parameter",1e1);
200  }
201 
203  const Ptr<BoundConstraint<Real>> &bnd,
204  const Vector<Real> &x,
205  const Vector<Real> &g,
206  const Vector<Real> &lam,
207  ParameterList &parlist)
208  : MoreauYosidaObjective(obj,bnd,x,g,parlist) {
209  lam_->set(lam);
210  }
211 
212  void updateMultipliers(Real mu, const Vector<Real> &x) {
213  if ( bnd_->isActivated() ) {
214  if ( updateMultiplier_ ) {
215  const Real one(1);
216  computePenalty(x);
217  lam_->set(*u1_);
218  lam_->axpy(-one,*l1_);
219  lam_->scale(mu_);
220  }
221  if ( updatePenalty_ ) {
222  mu_ = mu;
223  }
224  }
225  nfval_ = 0; ngrad_ = 0;
226  isPenEvaluated_ = false;
227  }
228 
229  void reset(const Real mu) {
230  lam_->zero();
231  mu_ = mu;
232  nfval_ = 0; ngrad_ = 0;
233  isPenEvaluated_ = false;
234  }
235 
237  Real val(0);
238  if (bnd_->isActivated()) {
239  computePenalty(x);
240 
241  tmp_->set(x);
242  tmp_->axpy(static_cast<Real>(-1), *l_);
243  Real lower = mu_*std::abs(tmp_->dot(*l1_));
244 
245  tmp_->set(x);
246  tmp_->axpy(static_cast<Real>(-1), *u_);
247  Real upper = mu_*std::abs(tmp_->dot(*u1_));
248 
249  tmp_->set(x);
250  bnd_->project(*tmp_);
251  tmp_->axpy(static_cast<Real>(-1), x);
252  Real xnorm = tmp_->norm();
253 
254  val = std::max(xnorm,std::max(lower,upper));
255  }
256  return val;
257  }
258 
259  Real getObjectiveValue(const Vector<Real> &x, Real &tol) {
260  int key(0);
261  Real val(0);
262  bool isComputed = fval_->get(val,key);
263  if (!isComputed) {
264  val = obj_->value(x,tol); nfval_++;
265  fval_->set(val,key);
266  }
267  return val;
268  }
269 
270  void getObjectiveGradient(Vector<Real> &g, const Vector<Real> &x, Real &tol) {
271  int key(0);
272  bool isComputed = gradient_->get(g,key);
273  if (!isComputed) {
274  obj_->gradient(g,x,tol); ngrad_++;
275  gradient_->set(g,key);
276  }
277  }
278 
280  return nfval_;
281  }
282 
284  return ngrad_;
285  }
286 
294  void update( const Vector<Real> &x, UpdateType type, int iter = -1 ) {
295  obj_->update(x,type,iter);
296  fval_->objectiveUpdate(type);
297  gradient_->objectiveUpdate(type);
298  // Need to do something smart here
299  isPenEvaluated_ = false;
300  }
301 
308  Real value( const Vector<Real> &x, Real &tol ) {
309  // Compute objective function value
310  Real fval = getObjectiveValue(x,tol);
311  // Add value of the Moreau-Yosida penalty
312  if ( bnd_->isActivated() ) {
313  const Real half(0.5);
314  computePenalty(x);
315  fval += half*mu_*(l1_->dot(*l1_) + u1_->dot(*u1_));
316  }
317  return fval;
318  }
319 
327  void gradient( Vector<Real> &g, const Vector<Real> &x, Real &tol ) {
328  // Compute gradient of objective function
329  getObjectiveGradient(g,x,tol);
330  // Add gradient of the Moreau-Yosida penalty
331  if ( bnd_->isActivated() ) {
332  computePenalty(x);
333  g.axpy(-mu_,*dl1_);
334  g.axpy(mu_,*du1_);
335  }
336  }
337 
346  void hessVec( Vector<Real> &hv, const Vector<Real> &v, const Vector<Real> &x, Real &tol ) {
347  // Apply objective Hessian to a vector
348  obj_->hessVec(hv,v,x,tol);
349  // Add Hessian of the Moreau-Yosida penalty
350  if ( bnd_->isActivated() ) {
351  const Real one(1);
352  computePenalty(x);
353 
354  v_->set(v);
355  bnd_->pruneLowerActive(*v_,*xlam_);
356  v_->scale(-one);
357  v_->plus(v);
358  dv_->set(v_->dual());
359  dv2_->set(*dv_);
360  bnd_->pruneLowerActive(*dv_,*xlam_);
361  dv_->scale(-one);
362  dv_->plus(*dv2_);
363  hv.axpy(mu_,*dv_);
364 
365  v_->set(v);
366  bnd_->pruneUpperActive(*v_,*xlam_);
367  v_->scale(-one);
368  v_->plus(v);
369  dv_->set(v_->dual());
370  dv2_->set(*dv_);
371  bnd_->pruneUpperActive(*dv_,*xlam_);
372  dv_->scale(-one);
373  dv_->plus(*dv2_);
374  hv.axpy(mu_,*dv_);
375  }
376  }
377 }; // class MoreauYosidaObjective
378 
379 } // namespace ROL
380 
381 #endif
Provides the interface to evaluate objective functions.
virtual ROL::Ptr< Vector > clone() const =0
Clone to make a new (uninitialized) vector.
virtual void axpy(const Real alpha, const Vector &x)
Compute where .
Definition: ROL_Vector.hpp:153
Real getObjectiveValue(const Vector< Real > &x, Real &tol)
Contains definitions of custom data types in ROL.
Real value(const Vector< Real > &x, Real &tol)
Compute value.
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:80
MoreauYosidaObjective(const Ptr< Objective< Real >> &obj, const Ptr< BoundConstraint< Real >> &bnd, const Vector< Real > &x, const Vector< Real > &g, const Vector< Real > &lam, ParameterList &parlist)
void hessVec(Vector< Real > &hv, const Vector< Real > &v, const Vector< Real > &x, Real &tol)
Apply Hessian approximation to vector.
Ptr< ScalarController< Real, int > > fval_
void updateMultipliers(Real mu, const Vector< Real > &x)
void update(const Vector< Real > &x, UpdateType type, int iter=-1)
Update Moreau-Yosida penalty function.
Provides the interface to evaluate the Moreau-Yosida penalty function.
void computePenalty(const Vector< Real > &x)
Provides the interface to apply upper and lower bound constraints.
const Ptr< BoundConstraint< Real > > bnd_
MoreauYosidaObjective(const Ptr< Objective< Real >> &obj, const Ptr< BoundConstraint< Real >> &bnd, const Vector< Real > &x, const Vector< Real > &g, const Real mu=1e1, const bool updateMultiplier=true, const bool updatePenalty=true)
MoreauYosidaObjective(const Ptr< Objective< Real >> &obj, const Ptr< BoundConstraint< Real >> &bnd, const Vector< Real > &x, const Vector< Real > &g, ParameterList &parlist)
void initialize(const Vector< Real > &x, const Vector< Real > &g)
void getObjectiveGradient(Vector< Real > &g, const Vector< Real > &x, Real &tol)
void gradient(Vector< Real > &g, const Vector< Real > &x, Real &tol)
Compute gradient.
Real testComplementarity(const Vector< Real > &x)
const Ptr< Objective< Real > > obj_
Ptr< VectorController< Real, int > > gradient_
MoreauYosidaObjective(const Ptr< Objective< Real >> &obj, const Ptr< BoundConstraint< Real >> &bnd, const Vector< Real > &x, const Vector< Real > &g, const Vector< Real > &lam, const Real mu=1e1, const bool updateMultiplier=true, const bool updatePenalty=true)