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
40namespace ROL {
41
42template<class Real>
43struct 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
51template<class Real>
52class NonlinearCG {
53private:
54
55 ROL::Ptr<NonlinearCGState<Real> > state_; // Nonlinear-CG State
56
57 ROL::Ptr<Vector<Real> > y_;
58 ROL::Ptr<Vector<Real> > yd_;
59
60public:
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
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
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
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
Contains definitions of custom data types in ROL.
ENonlinearCG
@ NONLINEARCG_POLAK_RIBIERE
@ NONLINEARCG_HESTENES_STIEFEL
@ NONLINEARCG_DAI_YUAN
@ NONLINEARCG_OREN_LUENBERGER
@ NONLINEARCG_DANIEL
@ NONLINEARCG_FLETCHER_REEVES
@ NONLINEARCG_HAGER_ZHANG
@ NONLINEARCG_LIU_STOREY
@ NONLINEARCG_FLETCHER_CONJDESC
int isValidNonlinearCG(ENonlinearCG s)
Verifies validity of a NonlinearCG enum.