ROL
ROL_NonlinearCG.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 
10 #ifndef ROL_NONLINEARCG_H
11 #define ROL_NONLINEARCG_H
12 
38 #include "ROL_Types.hpp"
39 
40 namespace ROL {
41 
42 template<class Real>
43 struct NonlinearCGState {
44  std::vector<ROL::Ptr<Vector<Real> > > grad; // Gradient Storage
45  std::vector<ROL::Ptr<Vector<Real> > > pstep; // Step Storage
46  int iter; // Nonlinear-CG Iteration Counter
47  int restart; // Reinitialize every 'restart' iterations
48  ENonlinearCG nlcg_type; // Nonlinear-CG Type
49 };
50 
51 template<class Real>
52 class NonlinearCG {
53 private:
54 
55  ROL::Ptr<NonlinearCGState<Real> > state_; // Nonlinear-CG State
56 
57  ROL::Ptr<Vector<Real> > y_;
58  ROL::Ptr<Vector<Real> > yd_;
59 
60 public:
61 
62  virtual ~NonlinearCG() {}
63 
64  // Constructor
65  NonlinearCG(ENonlinearCG type, int restart = 100) {
66  state_ = ROL::makePtr<NonlinearCGState<Real>>();
67  state_->iter = 0;
68  state_->grad.resize(1);
69  state_->pstep.resize(1);
70  ROL_TEST_FOR_EXCEPTION(!(isValidNonlinearCG(type)),
71  std::invalid_argument,
72  ">>> ERROR (ROL_NonlinearCG.hpp): Invalid nonlinear CG type in constructor!");
73  state_->nlcg_type = type;
74  ROL_TEST_FOR_EXCEPTION((restart < 1),
75  std::invalid_argument,
76  ">>> ERROR (ROL_NonlinearCG.hpp): Non-positive restart integer in constructor!");
77  state_->restart = restart;
78  }
79 
80  ROL::Ptr<NonlinearCGState<Real> >& get_state() { return this->state_; }
81 
82  // Run one step of nonlinear CG.
83  virtual void run( Vector<Real> &s , const Vector<Real> &g, const Vector<Real> &x, Objective<Real> &obj ) {
84  Real one(1);
85  // Initialize vector storage
86  if ( state_->iter == 0 ) {
87  if ( state_->nlcg_type != NONLINEARCG_FLETCHER_REEVES &&
88  state_->nlcg_type != NONLINEARCG_FLETCHER_CONJDESC ) {
89  y_ = g.clone();
90  }
91  if ( state_->nlcg_type == NONLINEARCG_HAGER_ZHANG ||
92  state_->nlcg_type == NONLINEARCG_OREN_LUENBERGER ) {
93  yd_ = g.clone();
94  }
95  }
96 
97  s.set(g.dual());
98 
99  if ((state_->iter % state_->restart) != 0) {
100  Real beta(0), zero(0);
101  switch(state_->nlcg_type) {
102 
104  y_->set(g);
105  y_->axpy(-one, *(state_->grad[0]));
106  beta = - g.dot(*y_) / (state_->pstep[0]->dot(y_->dual()));
107  beta = std::max(beta, zero);
108  break;
109  }
110 
112  beta = g.dot(g) / (state_->grad[0])->dot(*(state_->grad[0]));
113  break;
114  }
115 
116  case NONLINEARCG_DANIEL: {
117  Real htol(0);
118  obj.hessVec( *y_, *(state_->pstep[0]), x, htol );
119  beta = - g.dot(*y_) / (state_->pstep[0])->dot(y_->dual());
120  beta = std::max(beta, zero);
121  break;
122  }
123 
125  y_->set(g);
126  y_->axpy(-one, *(state_->grad[0]));
127  beta = g.dot(*y_) / (state_->grad[0])->dot(*(state_->grad[0]));
128  beta = std::max(beta, zero);
129  break;
130  }
131 
133  beta = g.dot(g) / (state_->pstep[0])->dot((state_->grad[0])->dual());
134  break;
135  }
136 
137  case NONLINEARCG_LIU_STOREY: {
138  y_->set(g);
139  y_->axpy(-one, *(state_->grad[0]));
140  beta = g.dot(*y_) / (state_->pstep[0])->dot((state_->grad[0])->dual());
141  //beta = std::max(beta, 0.0); // Is this needed? May need research.
142  break;
143  }
144 
145  case NONLINEARCG_DAI_YUAN: {
146  y_->set(g);
147  y_->axpy(-one, *(state_->grad[0]));
148  beta = - g.dot(g) / (state_->pstep[0])->dot(y_->dual());
149  break;
150  }
151 
153  Real eta_0(1e-2), two(2);
154  y_->set(g);
155  y_->axpy(-one, *(state_->grad[0]));
156  yd_->set(*y_);
157  Real mult = two * ( y_->dot(*y_) / (state_->pstep[0])->dot(y_->dual()) );
158  yd_->axpy(-mult, (state_->pstep[0])->dual());
159  beta = - yd_->dot(g) / (state_->pstep[0])->dot(y_->dual());
160  Real eta = -one / ((state_->pstep[0])->norm()*std::min(eta_0,(state_->grad[0])->norm()));
161  beta = std::max(beta, eta);
162  break;
163  }
164 
166  Real eta_0(1e-2);
167  y_->set(g);
168  y_->axpy(-one, *(state_->grad[0]));
169  yd_->set(*y_);
170  Real mult = ( y_->dot(*y_) / (state_->pstep[0])->dot(y_->dual()) );
171  yd_->axpy(-mult, (state_->pstep[0])->dual());
172  beta = - yd_->dot(g) / (state_->pstep[0])->dot(y_->dual());
173  Real eta = -one / ((state_->pstep[0])->norm()*std::min(eta_0,(state_->grad[0])->norm()));
174  beta = std::max(beta, eta);
175  break;
176  }
177 
178  default:
179  ROL_TEST_FOR_EXCEPTION(!(isValidNonlinearCG(state_->nlcg_type)),
180  std::invalid_argument,
181  ">>> ERROR (ROL_NonlinearCG.hpp): Invalid nonlinear CG type in the 'run' method!");
182  }
183 
184  s.axpy(beta, *(state_->pstep[0]));
185  }
186 
187  // Update storage.
188  if (state_->iter == 0) {
189  (state_->grad[0]) = g.clone();
190  (state_->pstep[0]) = s.clone();
191  }
192  (state_->grad[0])->set(g);
193  (state_->pstep[0])->set(s);
194  state_->iter++;
195  }
196 
197 };
198 
199 }
200 
201 #endif
Contains definitions of custom data types in ROL.
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
ENonlinearCG
Enumeration of nonlinear CG algorithms.
Definition: ROL_Types.hpp:532
int isValidNonlinearCG(ENonlinearCG s)
Verifies validity of a NonlinearCG enum.
Definition: ROL_Types.hpp:570