ROL
ROL_HelperFunctions.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 
15 #ifndef ROL_HELPERFUNCTIONS_HPP
16 #define ROL_HELPERFUNCTIONS_HPP
17 
18 #include "ROL_Vector.hpp"
19 #include "ROL_Objective.hpp"
20 #include "ROL_BoundConstraint.hpp"
21 #include "ROL_Secant.hpp"
22 #include "Teuchos_SerialDenseMatrix.hpp"
23 #include "Teuchos_SerialDenseVector.hpp"
24 #include "Teuchos_LAPACK.hpp"
25 
26 namespace ROL {
27 
28  template<class Real>
29  Teuchos::SerialDenseMatrix<int, Real> computeDenseHessian(Objective<Real> &obj, const Vector<Real> &x) {
30 
31  Real tol = std::sqrt(ROL_EPSILON<Real>());
32 
33  int dim = x.dimension();
34  Teuchos::SerialDenseMatrix<int, Real> H(dim, dim);
35 
36  ROL::Ptr<Vector<Real> > e = x.clone();
37  ROL::Ptr<Vector<Real> > h = x.dual().clone();
38 
39  for (int i=0; i<dim; i++) {
40  e = x.basis(i);
41  obj.hessVec(*h, *e, x, tol);
42  for (int j=0; j<dim; j++) {
43  e = x.basis(j);
44  //H(j,i) = e->dot(h->dual());
45  H(j,i) = e->apply(*h);
46  }
47  }
48 
49  return H;
50 
51  }
52 
53 
54  template<class Real>
55  Teuchos::SerialDenseMatrix<int, Real> computeScaledDenseHessian(Objective<Real> &obj, const Vector<Real> &x) {
56 
57  Real tol = std::sqrt(ROL_EPSILON<Real>());
58 
59  int dim = x.dimension();
60  Teuchos::SerialDenseMatrix<int, Real> H(dim, dim);
61 
62  ROL::Ptr<Vector<Real> > ei = x.clone();
63  ROL::Ptr<Vector<Real> > ej = x.dual().clone();
64  ROL::Ptr<Vector<Real> > h = x.dual().clone();
65 
66  for (int i=0; i<dim; i++) {
67  ei = ei->basis(i);
68  obj.hessVec(*h, *ei, x, tol);
69  for (int j=0; j<dim; j++) {
70  ej = ej->basis(j);
71  H(j,i) = ej->dot(*h);
72  }
73  }
74 
75  return H;
76 
77  }
78 
79 
80  template<class Real>
81  Teuchos::SerialDenseMatrix<int, Real> computeDotMatrix(const Vector<Real> &x) {
82 
83  int dim = x.dimension();
84  Teuchos::SerialDenseMatrix<int, Real> M(dim, dim);
85 
86  ROL::Ptr<Vector<Real> > ei = x.clone();
87  ROL::Ptr<Vector<Real> > ej = x.clone();
88 
89  for (int i=0; i<dim; i++) {
90  ei = x.basis(i);
91  for (int j=0; j<dim; j++) {
92  ej = x.basis(j);
93  M(j,i) = ej->dot(*ei);
94  }
95  }
96 
97  return M;
98 
99  }
100 
101  template<class Real>
102  std::vector<std::vector<Real> > computeEigenvalues(const Teuchos::SerialDenseMatrix<int, Real> & mat) {
103 
104  Teuchos::LAPACK<int, Real> lapack;
105 
106  Teuchos::SerialDenseMatrix<int, Real> mymat(Teuchos::Copy, mat);
107 
108  char jobvl = 'N';
109  char jobvr = 'N';
110 
111  int n = mat.numRows();
112 
113  std::vector<Real> real(n, 0);
114  std::vector<Real> imag(n, 0);
115  std::vector<std::vector<Real> > eigenvals;
116 
117  Real* vl = 0;
118  Real* vr = 0;
119 
120  int ldvl = 1;
121  int ldvr = 1;
122 
123  int lwork = 4*n;
124 
125  std::vector<Real> work(lwork, 0);
126 
127  int info = 0;
128 
129  lapack.GEEV(jobvl, jobvr, n, &mymat(0,0), n, &real[0], &imag[0], vl, ldvl, vr, ldvr, &work[0], lwork, &info);
130 
131  eigenvals.push_back(real);
132  eigenvals.push_back(imag);
133 
134  return eigenvals;
135 
136  }
137 
138 
139  template<class Real>
140  std::vector<std::vector<Real> > computeGenEigenvalues(const Teuchos::SerialDenseMatrix<int, Real> & A,
141  const Teuchos::SerialDenseMatrix<int, Real> & B) {
142 
143  Teuchos::LAPACK<int, Real> lapack;
144 
145  Teuchos::SerialDenseMatrix<int, Real> myA(Teuchos::Copy, A);
146  Teuchos::SerialDenseMatrix<int, Real> myB(Teuchos::Copy, B);
147 
148  char jobvl = 'N';
149  char jobvr = 'N';
150 
151  int n = A.numRows();
152 
153  std::vector<Real> real(n, 0);
154  std::vector<Real> imag(n, 0);
155  std::vector<Real> beta(n, 0);
156  std::vector<std::vector<Real> > eigenvals;
157 
158  Real* vl = 0;
159  Real* vr = 0;
160 
161  int ldvl = 1;
162  int ldvr = 1;
163 
164  int lwork = 10*n;
165 
166  std::vector<Real> work(lwork, 0);
167 
168  int info = 0;
169 
170  lapack.GGEV(jobvl, jobvr, n, &myA(0,0), n, &myB(0,0), n, &real[0], &imag[0], &beta[0],
171  vl, ldvl, vr, ldvr, &work[0], lwork, &info);
172 
173  for (int i=0; i<n; i++) {
174  real[i] /= beta[i];
175  imag[i] /= beta[i];
176  }
177 
178  eigenvals.push_back(real);
179  eigenvals.push_back(imag);
180 
181  return eigenvals;
182 
183  }
184 
185 
186  template<class Real>
187  Teuchos::SerialDenseMatrix<int, Real> computeInverse(const Teuchos::SerialDenseMatrix<int, Real> & mat) {
188 
189  Teuchos::LAPACK<int, Real> lapack;
190 
191  Teuchos::SerialDenseMatrix<int, Real> mymat(Teuchos::Copy, mat);
192 
193  int n = mat.numRows();
194 
195  std::vector<int> ipiv(n, 0);
196 
197  int lwork = 5*n;
198 
199  std::vector<Real> work(lwork, 0);
200 
201  int info = 0;
202 
203  lapack.GETRF(n, n, &mymat(0,0), n, &ipiv[0], &info);
204  lapack.GETRI(n, &mymat(0,0), n, &ipiv[0], &work[0], lwork, &info);
205 
206  return mymat;
207 
208  }
209 
210 
211 
212  template<class Real>
213  class ProjectedObjective : public Objective<Real> {
214  private:
215  ROL::Ptr<Objective<Real> > obj_;
216  ROL::Ptr<BoundConstraint<Real> > con_;
217  ROL::Ptr<Secant<Real> > secant_;
218 
219  ROL::Ptr<ROL::Vector<Real> > primalV_;
220  ROL::Ptr<ROL::Vector<Real> > dualV_;
222 
225  Real eps_;
226 
227  public:
229  ROL::Ptr<Secant<Real> > &secant,
230  bool useSecantPrecond = false,
231  bool useSecantHessVec = false,
232  Real eps = 0.0 )
233  : isInitialized_(false), useSecantPrecond_(useSecantPrecond),
234  useSecantHessVec_(useSecantHessVec), eps_(eps) {
235  obj_ = ROL::makePtrFromRef(obj);
236  con_ = ROL::makePtrFromRef(con);
237  secant_ = secant;
238  }
239 
240  void update( const Vector<Real> &x, bool flag = true, int iter = -1 ) {
241  obj_->update(x,flag,iter);
242  con_->update(x,flag,iter);
243  }
244 
245  Real value( const Vector<Real> &x, Real &tol ) {
246  return obj_->value(x,tol);
247  }
248 
249  void gradient( Vector<Real> &g, const Vector<Real> &x, Real &tol ) {
250  obj_->gradient(g,x,tol);
251  }
252 
253  Real dirDeriv( const Vector<Real> &x, const Vector<Real> &d, Real &tol ) {
254  return obj_->dirDeriv(x,d,tol);
255  }
256 
257  void hessVec( Vector<Real> &Hv, const Vector<Real> &v, const Vector<Real> &x, Real &tol ) {
258  if ( useSecantHessVec_ ) {
259  secant_->applyB( Hv, v );
260  }
261  else {
262  obj_->hessVec( Hv, v, x, tol );
263  }
264  }
265 
266  void invHessVec( Vector<Real> &Hv, const Vector<Real> &v, const Vector<Real> &x, Real &tol ) {
267  if ( useSecantHessVec_ ) {
268  secant_->applyH(Hv,v);
269  }
270  else {
271  obj_->invHessVec(Hv,v,x,tol);
272  }
273  }
274 
275  void precond( Vector<Real> &Mv, const Vector<Real> &v, const Vector<Real> &x, Real &tol ) {
276  if ( useSecantPrecond_ ) {
277  secant_->applyH( Mv, v );
278  }
279  else {
280  obj_->precond( Mv, v, x, tol );
281  }
282  }
283 
295  void reducedHessVec( Vector<Real> &Hv, const Vector<Real> &v, const Vector<Real> &p,
296  const Vector<Real> &d, const Vector<Real> &x, Real &tol ) {
297  if ( con_->isActivated() ) {
298  if (!isInitialized_) {
299  primalV_ = x.clone();
300  dualV_ = x.dual().clone();
301  isInitialized_ = true;
302  }
303  // Set vnew to v
304  primalV_->set(v);
305  // Remove elements of vnew corresponding to binding set
306  con_->pruneActive(*primalV_,d,p,eps_);
307  // Apply full Hessian to reduced vector
308  hessVec(Hv,*primalV_,x,tol);
309  // Remove elements of Hv corresponding to binding set
310  con_->pruneActive(Hv,d,p,eps_);
311  // Set vnew to v
312  primalV_->set(v);
313  // Remove Elements of vnew corresponding to complement of binding set
314  con_->pruneInactive(*primalV_,d,p,eps_);
315  dualV_->set(primalV_->dual());
316  con_->pruneInactive(*dualV_,d,p,eps_);
317  // Fill complement of binding set elements in Hp with v
318  Hv.plus(*dualV_);
319  }
320  else {
321  hessVec(Hv,v,x,tol);
322  }
323  }
324 
335  void reducedHessVec( Vector<Real> &Hv, const Vector<Real> &v, const Vector<Real> &p,
336  const Vector<Real> &x, Real &tol ) {
337  if ( con_->isActivated() ) {
338  if (!isInitialized_) {
339  primalV_ = x.clone();
340  dualV_ = x.dual().clone();
341  isInitialized_ = true;
342  }
343  // Set vnew to v
344  primalV_->set(v);
345  // Remove elements of vnew corresponding to binding set
346  con_->pruneActive(*primalV_,p,eps_);
347  // Apply full Hessian to reduced vector
348  hessVec(Hv,*primalV_,x,tol);
349  // Remove elements of Hv corresponding to binding set
350  con_->pruneActive(Hv,p,eps_);
351  // Set vnew to v
352  primalV_->set(v);
353  // Remove Elements of vnew corresponding to complement of binding set
354  con_->pruneInactive(*primalV_,p,eps_);
355  dualV_->set(primalV_->dual());
356  con_->pruneInactive(*dualV_,p,eps_);
357  // Fill complement of binding set elements in Hp with v
358  Hv.plus(*dualV_);
359  }
360  else {
361  hessVec(Hv,v,x,tol);
362  }
363  }
364 
376  void reducedInvHessVec( Vector<Real> &Hv, const Vector<Real> &v, const Vector<Real> &p,
377  const Vector<Real> &d, const Vector<Real> &x, Real &tol ) {
378  if ( con_->isActivated() ) {
379  if (!isInitialized_) {
380  primalV_ = x.clone();
381  dualV_ = x.dual().clone();
382  isInitialized_ = true;
383  }
384  // Set vnew to v
385  dualV_->set(v);
386  // Remove elements of vnew corresponding to binding set
387  con_->pruneActive(*dualV_,d,p,eps_);
388  // Apply full Hessian to reduced vector
389  invHessVec(Hv,*dualV_,x,tol);
390  // Remove elements of Hv corresponding to binding set
391  con_->pruneActive(Hv,d,p,eps_);
392  // Set vnew to v
393  dualV_->set(v);
394  // Remove Elements of vnew corresponding to complement of binding set
395  con_->pruneInactive(*dualV_,d,p,eps_);
396  primalV_->set(dualV_->dual());
397  con_->pruneInactive(*primalV_,d,p,eps_);
398  // Fill complement of binding set elements in Hv with v
399  Hv.plus(*primalV_);
400  }
401  else {
402  invHessVec(Hv,v,x,tol);
403  }
404  }
405 
416  void reducedInvHessVec( Vector<Real> &Hv, const Vector<Real> &v, const Vector<Real> &p,
417  const Vector<Real> &x, Real &tol ) {
418  if ( con_->isActivated() ) {
419  if (!isInitialized_) {
420  primalV_ = x.clone();
421  dualV_ = x.dual().clone();
422  isInitialized_ = true;
423  }
424  // Set vnew to v
425  dualV_->set(v);
426  // Remove elements of vnew corresponding to binding set
427  con_->pruneActive(*dualV_,p,eps_);
428  // Apply full Hessian to reduced vector
429  invHessVec(Hv,*dualV_,x,tol);
430  // Remove elements of Hv corresponding to binding set
431  con_->pruneActive(Hv,p,eps_);
432  // Set vnew to v
433  dualV_->set(v);
434  // Remove Elements of vnew corresponding to complement of binding set
435  con_->pruneInactive(*dualV_,p,eps_);
436  primalV_->set(dualV_->dual());
437  con_->pruneInactive(*primalV_,p,eps_);
438  // Fill complement of binding set elements in Hv with v
439  Hv.plus(*primalV_);
440  }
441  else {
442  invHessVec(Hv,v,x,tol);
443  }
444  }
445 
457  void reducedPrecond( Vector<Real> &Mv, const Vector<Real> &v, const Vector<Real> &p,
458  const Vector<Real> &d, const Vector<Real> &x, Real &tol ) {
459  if ( con_->isActivated() ) {
460  if (!isInitialized_) {
461  primalV_ = x.clone();
462  dualV_ = x.dual().clone();
463  isInitialized_ = true;
464  }
465  // Set vnew to v
466  dualV_->set(v);
467  // Remove elements of vnew corresponding to binding set
468  con_->pruneActive(*dualV_,d,p,eps_);
469  // Apply full Hessian to reduced vector
470  precond(Mv,*dualV_,x,tol);
471  // Remove elements of Mv corresponding to binding set
472  con_->pruneActive(Mv,d,p,eps_);
473  // Set vnew to v
474  dualV_->set(v);
475  // Remove Elements of vnew corresponding to complement of binding set
476  con_->pruneInactive(*dualV_,d,p,eps_);
477  primalV_->set(dualV_->dual());
478  con_->pruneInactive(*primalV_,d,p,eps_);
479  // Fill complement of binding set elements in Mv with v
480  Mv.plus(*primalV_);
481  }
482  else {
483  precond(Mv,v,x,tol);
484  }
485  }
486 
497  void reducedPrecond( Vector<Real> &Mv, const Vector<Real> &v, const Vector<Real> &p,
498  const Vector<Real> &x, Real &tol ) {
499  if ( con_->isActivated() ) {
500  if (!isInitialized_) {
501  primalV_ = x.clone();
502  dualV_ = x.dual().clone();
503  isInitialized_ = true;
504  }
505  // Set vnew to v
506  dualV_->set(v);
507  // Remove elements of vnew corresponding to binding set
508  con_->pruneActive(*dualV_,p,eps_);
509  // Apply full Hessian to reduced vector
510  precond(Mv,*dualV_,x,tol);
511  // Remove elements of Mv corresponding to binding set
512  con_->pruneActive(Mv,p,eps_);
513  // Set vnew to v
514  dualV_->set(v);
515  // Remove Elements of vnew corresponding to complement of binding set
516  con_->pruneInactive(*dualV_,p,eps_);
517  primalV_->set(dualV_->dual());
518  con_->pruneInactive(*primalV_,p,eps_);
519  // Fill complement of binding set elements in Mv with v
520  Mv.plus(*primalV_);
521  }
522  else {
523  precond(Mv,v,x,tol);
524  }
525  }
526 
527  void project( Vector<Real> &x ) {
528  con_->project(x);
529  }
530 
531  void pruneActive( Vector<Real> &v, const Vector<Real> &g, const Vector<Real> &x ) {
532  con_->pruneActive(v,g,x,eps_);
533  }
534 
535  void pruneActive( Vector<Real> &v, const Vector<Real> &x ) {
536  con_->pruneActive(v,x,eps_);
537  }
538 
539  void pruneInactive( Vector<Real> &v, const Vector<Real> &g, const Vector<Real> &x ) {
540  con_->pruneInactive(v,g,x,eps_);
541  }
542 
543  void pruneInactive( Vector<Real> &v, const Vector<Real> &x ) {
544  con_->pruneInactive(v,x,eps_);
545  }
546 
547  bool isFeasible( const Vector<Real> &v ) {
548  return con_->isFeasible(v);
549  }
550 
551  bool isConActivated(void) {
552  return con_->isActivated();
553  }
554 
556  con_->computeProjectedStep(v,x);
557  }
558  };
559 
560 } // namespace ROL
561 
562 #endif
Provides the interface to evaluate objective functions.
virtual const Vector & dual() const
Return dual representation of , for example, the result of applying a Riesz map, or change of basis...
Definition: ROL_Vector.hpp:192
Real value(const Vector< Real > &x, Real &tol)
Compute value.
ROL::Ptr< Secant< Real > > secant_
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:162
ROL::Ptr< ROL::Vector< Real > > primalV_
virtual ROL::Ptr< Vector > basis(const int i) const
Return i-th basis vector.
Definition: ROL_Vector.hpp:148
virtual void plus(const Vector &x)=0
Compute , where .
void reducedHessVec(Vector< Real > &Hv, const Vector< Real > &v, const Vector< Real > &p, const Vector< Real > &d, const Vector< Real > &x, Real &tol)
Apply the reduced Hessian to a vector, v. The reduced Hessian first removes elements of v correspondi...
virtual void hessVec(Vector< Real > &hv, const Vector< Real > &v, const Vector< Real > &x, Real &tol)
Apply Hessian approximation to vector.
Real dirDeriv(const Vector< Real > &x, const Vector< Real > &d, Real &tol)
Compute directional derivative.
void pruneInactive(Vector< Real > &v, const Vector< Real > &g, const Vector< Real > &x)
Teuchos::SerialDenseMatrix< int, Real > computeScaledDenseHessian(Objective< Real > &obj, const Vector< Real > &x)
ProjectedObjective(Objective< Real > &obj, BoundConstraint< Real > &con, ROL::Ptr< Secant< Real > > &secant, bool useSecantPrecond=false, bool useSecantHessVec=false, Real eps=0.0)
ROL::Ptr< Objective< Real > > obj_
bool isFeasible(const Vector< Real > &v)
void pruneActive(Vector< Real > &v, const Vector< Real > &g, const Vector< Real > &x)
void reducedPrecond(Vector< Real > &Mv, const Vector< Real > &v, const Vector< Real > &p, const Vector< Real > &x, Real &tol)
Apply the reduced preconditioner to a vector, v. The reduced preconditioner first removes elements of...
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:46
void hessVec(Vector< Real > &Hv, const Vector< Real > &v, const Vector< Real > &x, Real &tol)
Apply Hessian approximation to vector.
Teuchos::SerialDenseMatrix< int, Real > computeDenseHessian(Objective< Real > &obj, const Vector< Real > &x)
std::vector< std::vector< Real > > computeGenEigenvalues(const Teuchos::SerialDenseMatrix< int, Real > &A, const Teuchos::SerialDenseMatrix< int, Real > &B)
void reducedInvHessVec(Vector< Real > &Hv, const Vector< Real > &v, const Vector< Real > &p, const Vector< Real > &x, Real &tol)
Apply the reduced inverse Hessian to a vector, v. The reduced inverse Hessian first removes elements ...
Provides interface for and implements limited-memory secant operators.
Definition: ROL_Secant.hpp:45
ROL::Ptr< ROL::Vector< Real > > dualV_
std::vector< std::vector< Real > > computeEigenvalues(const Teuchos::SerialDenseMatrix< int, Real > &mat)
void reducedInvHessVec(Vector< Real > &Hv, const Vector< Real > &v, const Vector< Real > &p, const Vector< Real > &d, const Vector< Real > &x, Real &tol)
Apply the reduced inverse Hessian to a vector, v. The reduced inverse Hessian first removes elements ...
void pruneInactive(Vector< Real > &v, const Vector< Real > &x)
void reducedHessVec(Vector< Real > &Hv, const Vector< Real > &v, const Vector< Real > &p, const Vector< Real > &x, Real &tol)
Apply the reduced Hessian to a vector, v. The reduced Hessian first removes elements of v correspondi...
Provides the interface to apply upper and lower bound constraints.
void gradient(Vector< Real > &g, const Vector< Real > &x, Real &tol)
Compute gradient.
void update(const Vector< Real > &x, bool flag=true, int iter=-1)
Update objective function.
Teuchos::SerialDenseMatrix< int, Real > computeDotMatrix(const Vector< Real > &x)
ROL::Ptr< BoundConstraint< Real > > con_
void computeProjectedStep(Vector< Real > &v, const Vector< Real > &x)
void reducedPrecond(Vector< Real > &Mv, const Vector< Real > &v, const Vector< Real > &p, const Vector< Real > &d, const Vector< Real > &x, Real &tol)
Apply the reduced preconditioner to a vector, v. The reduced preconditioner first removes elements of...
void project(Vector< Real > &x)
void invHessVec(Vector< Real > &Hv, const Vector< Real > &v, const Vector< Real > &x, Real &tol)
Apply inverse Hessian approximation to vector.
Teuchos::SerialDenseMatrix< int, Real > computeInverse(const Teuchos::SerialDenseMatrix< int, Real > &mat)
void precond(Vector< Real > &Mv, const Vector< Real > &v, const Vector< Real > &x, Real &tol)
Apply preconditioner to vector.
constexpr auto dim
void pruneActive(Vector< Real > &v, const Vector< Real > &x)