ROL
ROL_ObjectiveDef.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_OBJECTIVE_DEF_H
45 #define ROL_OBJECTIVE_DEF_H
46 
51 namespace ROL {
52 
53 template <class Real>
54 Real Objective<Real>::dirDeriv( const Vector<Real> &x, const Vector<Real> &d, Real &tol) {
55  Real ftol = std::sqrt(ROL_EPSILON<Real>());
56 
57  ROL::Ptr<Vector<Real> > xd = d.clone();
58  xd->set(x);
59  xd->axpy(tol, d);
60  return (this->value(*xd,ftol) - this->value(x,ftol)) / tol;
61 }
62 
63 template <class Real>
64 void Objective<Real>::gradient( Vector<Real> &g, const Vector<Real> &x, Real &tol ) {
65  g.zero();
66  Real deriv = 0.0, h = 0.0, xi = 0.0;
67  for (int i = 0; i < g.dimension(); i++) {
68  xi = std::abs(x.dot(*x.basis(i)));
69  h = ((xi < ROL_EPSILON<Real>()) ? 1. : xi)*tol;
70  deriv = this->dirDeriv(x,*x.basis(i),h);
71  g.axpy(deriv,*g.basis(i));
72  }
73 }
74 
75 template <class Real>
76 void Objective<Real>::hessVec( Vector<Real> &hv, const Vector<Real> &v, const Vector<Real> &x, Real &tol ) {
77  Real zero(0), one(1);
78  // Get Step Length
79  if ( v.norm() == zero ) {
80  hv.zero();
81  }
82  else {
83  Real gtol = std::sqrt(ROL_EPSILON<Real>());
84 
85  Real h = std::max(one,x.norm()/v.norm())*tol;
86  //Real h = 2.0/(v.norm()*v.norm())*tol;
87 
88  // Compute Gradient at x
89  ROL::Ptr<Vector<Real> > g = hv.clone();
90  this->gradient(*g,x,gtol);
91 
92  // Compute New Step x + h*v
93  ROL::Ptr<Vector<Real> > xnew = x.clone();
94  xnew->set(x);
95  xnew->axpy(h,v);
96  this->update(*xnew);
97 
98  // Compute Gradient at x + h*v
99  hv.zero();
100  this->gradient(hv,*xnew,gtol);
101 
102  // Compute Newton Quotient
103  hv.axpy(-one,*g);
104  hv.scale(one/h);
105  }
106 }
107 
108 
109 
110 template <class Real>
111 std::vector<std::vector<Real> > Objective<Real>::checkGradient( const Vector<Real> &x,
112  const Vector<Real> &g,
113  const Vector<Real> &d,
114  const bool printToStream,
115  std::ostream & outStream,
116  const int numSteps,
117  const int order ) {
118 
119  std::vector<Real> steps(numSteps);
120  for(int i=0;i<numSteps;++i) {
121  steps[i] = pow(10,-i);
122  }
123 
124  return checkGradient(x,g,d,steps,printToStream,outStream,order);
125 
126 } // checkGradient
127 
128 
129 
130 template <class Real>
131 std::vector<std::vector<Real> > Objective<Real>::checkGradient( const Vector<Real> &x,
132  const Vector<Real> &g,
133  const Vector<Real> &d,
134  const std::vector<Real> &steps,
135  const bool printToStream,
136  std::ostream & outStream,
137  const int order ) {
138 
139  ROL_TEST_FOR_EXCEPTION( order<1 || order>4, std::invalid_argument,
140  "Error: finite difference order must be 1,2,3, or 4" );
141 
144 
145  Real tol = std::sqrt(ROL_EPSILON<Real>());
146 
147  int numSteps = steps.size();
148  int numVals = 4;
149  std::vector<Real> tmp(numVals);
150  std::vector<std::vector<Real> > gCheck(numSteps, tmp);
151 
152  // Save the format state of the original outStream.
153  ROL::nullstream oldFormatState;
154  oldFormatState.copyfmt(outStream);
155 
156  // Evaluate objective value at x.
157  this->update(x);
158  Real val = this->value(x,tol);
159 
160  // Compute gradient at x.
161  ROL::Ptr<Vector<Real> > gtmp = g.clone();
162  this->update(x);
163  this->gradient(*gtmp, x, tol);
164  Real dtg = d.dot(gtmp->dual());
165 
166  // Temporary vectors.
167  ROL::Ptr<Vector<Real> > xnew = x.clone();
168 
169  for (int i=0; i<numSteps; i++) {
170 
171  Real eta = steps[i];
172 
173  xnew->set(x);
174 
175  // Compute gradient, finite-difference gradient, and absolute error.
176  gCheck[i][0] = eta;
177  gCheck[i][1] = dtg;
178 
179  gCheck[i][2] = weights[order-1][0] * val;
180 
181  for(int j=0; j<order; ++j) {
182  // Evaluate at x <- x+eta*c_i*d.
183  xnew->axpy(eta*shifts[order-1][j], d);
184 
185  // Only evaluate at shifts where the weight is nonzero
186  if( weights[order-1][j+1] != 0 ) {
187  this->update(*xnew);
188  gCheck[i][2] += weights[order-1][j+1] * this->value(*xnew,tol);
189  }
190  }
191 
192  gCheck[i][2] /= eta;
193 
194  gCheck[i][3] = std::abs(gCheck[i][2] - gCheck[i][1]);
195 
196  if (printToStream) {
197  if (i==0) {
198  outStream << std::right
199  << std::setw(20) << "Step size"
200  << std::setw(20) << "grad'*dir"
201  << std::setw(20) << "FD approx"
202  << std::setw(20) << "abs error"
203  << "\n"
204  << std::setw(20) << "---------"
205  << std::setw(20) << "---------"
206  << std::setw(20) << "---------"
207  << std::setw(20) << "---------"
208  << "\n";
209  }
210  outStream << std::scientific << std::setprecision(11) << std::right
211  << std::setw(20) << gCheck[i][0]
212  << std::setw(20) << gCheck[i][1]
213  << std::setw(20) << gCheck[i][2]
214  << std::setw(20) << gCheck[i][3]
215  << "\n";
216  }
217 
218  }
219 
220  // Reset format state of outStream.
221  outStream.copyfmt(oldFormatState);
222 
223  return gCheck;
224 } // checkGradient
225 
226 
227 
228 
229 
230 
231 
232 
233 template <class Real>
234 std::vector<std::vector<Real> > Objective<Real>::checkHessVec( const Vector<Real> &x,
235  const Vector<Real> &hv,
236  const Vector<Real> &v,
237  const bool printToStream,
238  std::ostream & outStream,
239  const int numSteps,
240  const int order ) {
241  std::vector<Real> steps(numSteps);
242  for(int i=0;i<numSteps;++i) {
243  steps[i] = pow(10,-i);
244  }
245 
246  return checkHessVec(x,hv,v,steps,printToStream,outStream,order);
247 } // checkHessVec
248 
249 
250 
251 template <class Real>
252 std::vector<std::vector<Real> > Objective<Real>::checkHessVec( const Vector<Real> &x,
253  const Vector<Real> &hv,
254  const Vector<Real> &v,
255  const std::vector<Real> &steps,
256  const bool printToStream,
257  std::ostream & outStream,
258  const int order ) {
259 
260  ROL_TEST_FOR_EXCEPTION( order<1 || order>4, std::invalid_argument,
261  "Error: finite difference order must be 1,2,3, or 4" );
262 
265 
266 
267  Real tol = std::sqrt(ROL_EPSILON<Real>());
268 
269  int numSteps = steps.size();
270  int numVals = 4;
271  std::vector<Real> tmp(numVals);
272  std::vector<std::vector<Real> > hvCheck(numSteps, tmp);
273 
274  // Save the format state of the original outStream.
275  ROL::nullstream oldFormatState;
276  oldFormatState.copyfmt(outStream);
277 
278  // Compute gradient at x.
279  ROL::Ptr<Vector<Real> > g = hv.clone();
280  this->update(x);
281  this->gradient(*g, x, tol);
282 
283  // Compute (Hessian at x) times (vector v).
284  ROL::Ptr<Vector<Real> > Hv = hv.clone();
285  this->hessVec(*Hv, v, x, tol);
286  Real normHv = Hv->norm();
287 
288  // Temporary vectors.
289  ROL::Ptr<Vector<Real> > gdif = hv.clone();
290  ROL::Ptr<Vector<Real> > gnew = hv.clone();
291  ROL::Ptr<Vector<Real> > xnew = x.clone();
292 
293  for (int i=0; i<numSteps; i++) {
294 
295  Real eta = steps[i];
296 
297  // Evaluate objective value at x+eta*d.
298  xnew->set(x);
299 
300  gdif->set(*g);
301  gdif->scale(weights[order-1][0]);
302 
303  for(int j=0; j<order; ++j) {
304 
305  // Evaluate at x <- x+eta*c_i*d.
306  xnew->axpy(eta*shifts[order-1][j], v);
307 
308  // Only evaluate at shifts where the weight is nonzero
309  if( weights[order-1][j+1] != 0 ) {
310  this->update(*xnew);
311  this->gradient(*gnew, *xnew, tol);
312  gdif->axpy(weights[order-1][j+1],*gnew);
313  }
314 
315  }
316 
317  gdif->scale(1.0/eta);
318 
319  // Compute norms of hessvec, finite-difference hessvec, and error.
320  hvCheck[i][0] = eta;
321  hvCheck[i][1] = normHv;
322  hvCheck[i][2] = gdif->norm();
323  gdif->axpy(-1.0, *Hv);
324  hvCheck[i][3] = gdif->norm();
325 
326  if (printToStream) {
327  if (i==0) {
328  outStream << std::right
329  << std::setw(20) << "Step size"
330  << std::setw(20) << "norm(Hess*vec)"
331  << std::setw(20) << "norm(FD approx)"
332  << std::setw(20) << "norm(abs error)"
333  << "\n"
334  << std::setw(20) << "---------"
335  << std::setw(20) << "--------------"
336  << std::setw(20) << "---------------"
337  << std::setw(20) << "---------------"
338  << "\n";
339  }
340  outStream << std::scientific << std::setprecision(11) << std::right
341  << std::setw(20) << hvCheck[i][0]
342  << std::setw(20) << hvCheck[i][1]
343  << std::setw(20) << hvCheck[i][2]
344  << std::setw(20) << hvCheck[i][3]
345  << "\n";
346  }
347 
348  }
349 
350  // Reset format state of outStream.
351  outStream.copyfmt(oldFormatState);
352 
353  return hvCheck;
354 } // checkHessVec
355 
356 
357 
358 template<class Real>
359 std::vector<Real> Objective<Real>::checkHessSym( const Vector<Real> &x,
360  const Vector<Real> &hv,
361  const Vector<Real> &v,
362  const Vector<Real> &w,
363  const bool printToStream,
364  std::ostream & outStream ) {
365 
366  Real tol = std::sqrt(ROL_EPSILON<Real>());
367 
368  // Compute (Hessian at x) times (vector v).
369  ROL::Ptr<Vector<Real> > h = hv.clone();
370  this->hessVec(*h, v, x, tol);
371  Real wHv = w.dot(h->dual());
372 
373  this->hessVec(*h, w, x, tol);
374  Real vHw = v.dot(h->dual());
375 
376  std::vector<Real> hsymCheck(3, 0);
377 
378  hsymCheck[0] = wHv;
379  hsymCheck[1] = vHw;
380  hsymCheck[2] = std::abs(vHw-wHv);
381 
382  // Save the format state of the original outStream.
383  ROL::nullstream oldFormatState;
384  oldFormatState.copyfmt(outStream);
385 
386  if (printToStream) {
387  outStream << std::right
388  << std::setw(20) << "<w, H(x)v>"
389  << std::setw(20) << "<v, H(x)w>"
390  << std::setw(20) << "abs error"
391  << "\n";
392  outStream << std::scientific << std::setprecision(11) << std::right
393  << std::setw(20) << hsymCheck[0]
394  << std::setw(20) << hsymCheck[1]
395  << std::setw(20) << hsymCheck[2]
396  << "\n";
397  }
398 
399  // Reset format state of outStream.
400  outStream.copyfmt(oldFormatState);
401 
402  return hsymCheck;
403 
404 } // checkHessSym
405 
406 
407 
408 } // namespace ROL
409 
410 #endif
virtual void scale(const Real alpha)=0
Compute where .
virtual ROL::Ptr< Vector > clone() const =0
Clone to make a new (uninitialized) vector.
virtual int dimension() const
Return dimension of the vector space.
Definition: ROL_Vector.hpp:196
virtual ROL::Ptr< Vector > basis(const int i) const
Return i-th basis vector.
Definition: ROL_Vector.hpp:182
const double weights[4][5]
Definition: ROL_Types.hpp:937
virtual void axpy(const Real alpha, const Vector &x)
Compute where .
Definition: ROL_Vector.hpp:153
virtual void update(const Vector< Real > &u, const Vector< Real > &z, bool flag=true, int iter=-1) override
virtual Real dirDeriv(const Vector< Real > &x, const Vector< Real > &d, Real &tol)
Compute directional derivative.
virtual void hessVec(Vector< Real > &hv, const Vector< Real > &v, const Vector< Real > &x, Real &tol)
Apply Hessian approximation to vector.
ROL::Objective_SimOpt value
virtual void zero()
Set to zero vector.
Definition: ROL_Vector.hpp:167
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:80
virtual Real dot(const Vector &x) const =0
Compute where .
virtual std::vector< std::vector< Real > > checkGradient(const Vector< Real > &x, const Vector< Real > &d, const bool printToStream=true, std::ostream &outStream=std::cout, const int numSteps=ROL_NUM_CHECKDERIV_STEPS, const int order=1)
Finite-difference gradient check.
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
virtual void gradient(Vector< Real > &g, const Vector< Real > &x, Real &tol)
Compute gradient.
basic_nullstream< char, char_traits< char >> nullstream
Definition: ROL_Stream.hpp:72
virtual std::vector< std::vector< Real > > checkHessVec(const Vector< Real > &x, const Vector< Real > &v, const bool printToStream=true, std::ostream &outStream=std::cout, const int numSteps=ROL_NUM_CHECKDERIV_STEPS, const int order=1)
Finite-difference Hessian-applied-to-vector check.
virtual Real norm() const =0
Returns where .
virtual std::vector< Real > checkHessSym(const Vector< Real > &x, const Vector< Real > &v, const Vector< Real > &w, const bool printToStream=true, std::ostream &outStream=std::cout)
Hessian symmetry check.