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->gradient(*gtmp, x, tol);
163  Real dtg = d.dot(gtmp->dual());
164 
165  // Temporary vectors.
166  ROL::Ptr<Vector<Real> > xnew = x.clone();
167 
168  for (int i=0; i<numSteps; i++) {
169 
170  Real eta = steps[i];
171 
172  xnew->set(x);
173 
174  // Compute gradient, finite-difference gradient, and absolute error.
175  gCheck[i][0] = eta;
176  gCheck[i][1] = dtg;
177 
178  gCheck[i][2] = weights[order-1][0] * val;
179 
180  for(int j=0; j<order; ++j) {
181  // Evaluate at x <- x+eta*c_i*d.
182  xnew->axpy(eta*shifts[order-1][j], d);
183 
184  // Only evaluate at shifts where the weight is nonzero
185  if( weights[order-1][j+1] != 0 ) {
186  this->update(*xnew);
187  gCheck[i][2] += weights[order-1][j+1] * this->value(*xnew,tol);
188  }
189  }
190 
191  gCheck[i][2] /= eta;
192 
193  gCheck[i][3] = std::abs(gCheck[i][2] - gCheck[i][1]);
194 
195  if (printToStream) {
196  if (i==0) {
197  outStream << std::right
198  << std::setw(20) << "Step size"
199  << std::setw(20) << "grad'*dir"
200  << std::setw(20) << "FD approx"
201  << std::setw(20) << "abs error"
202  << "\n"
203  << std::setw(20) << "---------"
204  << std::setw(20) << "---------"
205  << std::setw(20) << "---------"
206  << std::setw(20) << "---------"
207  << "\n";
208  }
209  outStream << std::scientific << std::setprecision(11) << std::right
210  << std::setw(20) << gCheck[i][0]
211  << std::setw(20) << gCheck[i][1]
212  << std::setw(20) << gCheck[i][2]
213  << std::setw(20) << gCheck[i][3]
214  << "\n";
215  }
216 
217  }
218 
219  // Reset format state of outStream.
220  outStream.copyfmt(oldFormatState);
221 
222  return gCheck;
223 } // checkGradient
224 
225 
226 
227 
228 
229 
230 
231 
232 template <class Real>
233 std::vector<std::vector<Real> > Objective<Real>::checkHessVec( const Vector<Real> &x,
234  const Vector<Real> &hv,
235  const Vector<Real> &v,
236  const bool printToStream,
237  std::ostream & outStream,
238  const int numSteps,
239  const int order ) {
240  std::vector<Real> steps(numSteps);
241  for(int i=0;i<numSteps;++i) {
242  steps[i] = pow(10,-i);
243  }
244 
245  return checkHessVec(x,hv,v,steps,printToStream,outStream,order);
246 } // checkHessVec
247 
248 
249 
250 template <class Real>
251 std::vector<std::vector<Real> > Objective<Real>::checkHessVec( const Vector<Real> &x,
252  const Vector<Real> &hv,
253  const Vector<Real> &v,
254  const std::vector<Real> &steps,
255  const bool printToStream,
256  std::ostream & outStream,
257  const int order ) {
258 
259  ROL_TEST_FOR_EXCEPTION( order<1 || order>4, std::invalid_argument,
260  "Error: finite difference order must be 1,2,3, or 4" );
261 
264 
265 
266  Real tol = std::sqrt(ROL_EPSILON<Real>());
267 
268  int numSteps = steps.size();
269  int numVals = 4;
270  std::vector<Real> tmp(numVals);
271  std::vector<std::vector<Real> > hvCheck(numSteps, tmp);
272 
273  // Save the format state of the original outStream.
274  ROL::nullstream oldFormatState;
275  oldFormatState.copyfmt(outStream);
276 
277  // Compute gradient at x.
278  ROL::Ptr<Vector<Real> > g = hv.clone();
279  this->update(x);
280  this->gradient(*g, x, tol);
281 
282  // Compute (Hessian at x) times (vector v).
283  ROL::Ptr<Vector<Real> > Hv = hv.clone();
284  this->hessVec(*Hv, v, x, tol);
285  Real normHv = Hv->norm();
286 
287  // Temporary vectors.
288  ROL::Ptr<Vector<Real> > gdif = hv.clone();
289  ROL::Ptr<Vector<Real> > gnew = hv.clone();
290  ROL::Ptr<Vector<Real> > xnew = x.clone();
291 
292  for (int i=0; i<numSteps; i++) {
293 
294  Real eta = steps[i];
295 
296  // Evaluate objective value at x+eta*d.
297  xnew->set(x);
298 
299  gdif->set(*g);
300  gdif->scale(weights[order-1][0]);
301 
302  for(int j=0; j<order; ++j) {
303 
304  // Evaluate at x <- x+eta*c_i*d.
305  xnew->axpy(eta*shifts[order-1][j], v);
306 
307  // Only evaluate at shifts where the weight is nonzero
308  if( weights[order-1][j+1] != 0 ) {
309  this->update(*xnew);
310  this->gradient(*gnew, *xnew, tol);
311  gdif->axpy(weights[order-1][j+1],*gnew);
312  }
313 
314  }
315 
316  gdif->scale(1.0/eta);
317 
318  // Compute norms of hessvec, finite-difference hessvec, and error.
319  hvCheck[i][0] = eta;
320  hvCheck[i][1] = normHv;
321  hvCheck[i][2] = gdif->norm();
322  gdif->axpy(-1.0, *Hv);
323  hvCheck[i][3] = gdif->norm();
324 
325  if (printToStream) {
326  if (i==0) {
327  outStream << std::right
328  << std::setw(20) << "Step size"
329  << std::setw(20) << "norm(Hess*vec)"
330  << std::setw(20) << "norm(FD approx)"
331  << std::setw(20) << "norm(abs error)"
332  << "\n"
333  << std::setw(20) << "---------"
334  << std::setw(20) << "--------------"
335  << std::setw(20) << "---------------"
336  << std::setw(20) << "---------------"
337  << "\n";
338  }
339  outStream << std::scientific << std::setprecision(11) << std::right
340  << std::setw(20) << hvCheck[i][0]
341  << std::setw(20) << hvCheck[i][1]
342  << std::setw(20) << hvCheck[i][2]
343  << std::setw(20) << hvCheck[i][3]
344  << "\n";
345  }
346 
347  }
348 
349  // Reset format state of outStream.
350  outStream.copyfmt(oldFormatState);
351 
352  return hvCheck;
353 } // checkHessVec
354 
355 
356 
357 template<class Real>
358 std::vector<Real> Objective<Real>::checkHessSym( const Vector<Real> &x,
359  const Vector<Real> &hv,
360  const Vector<Real> &v,
361  const Vector<Real> &w,
362  const bool printToStream,
363  std::ostream & outStream ) {
364 
365  Real tol = std::sqrt(ROL_EPSILON<Real>());
366 
367  // Compute (Hessian at x) times (vector v).
368  ROL::Ptr<Vector<Real> > h = hv.clone();
369  this->hessVec(*h, v, x, tol);
370  Real wHv = w.dot(h->dual());
371 
372  this->hessVec(*h, w, x, tol);
373  Real vHw = v.dot(h->dual());
374 
375  std::vector<Real> hsymCheck(3, 0);
376 
377  hsymCheck[0] = wHv;
378  hsymCheck[1] = vHw;
379  hsymCheck[2] = std::abs(vHw-wHv);
380 
381  // Save the format state of the original outStream.
382  ROL::nullstream oldFormatState;
383  oldFormatState.copyfmt(outStream);
384 
385  if (printToStream) {
386  outStream << std::right
387  << std::setw(20) << "<w, H(x)v>"
388  << std::setw(20) << "<v, H(x)w>"
389  << std::setw(20) << "abs error"
390  << "\n";
391  outStream << std::scientific << std::setprecision(11) << std::right
392  << std::setw(20) << hsymCheck[0]
393  << std::setw(20) << hsymCheck[1]
394  << std::setw(20) << hsymCheck[2]
395  << "\n";
396  }
397 
398  // Reset format state of outStream.
399  outStream.copyfmt(oldFormatState);
400 
401  return hsymCheck;
402 
403 } // checkHessSym
404 
405 
406 
407 } // namespace ROL
408 
409 #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:866
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.