ROL
ROL_Secant.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_SECANT_H
11#define ROL_SECANT_H
12
17#include "ROL_ParameterList.hpp"
19#include "ROL_Types.hpp"
20
21namespace ROL {
22
28
29template<class Real>
31 Ptr<Vector<Real>> iterate;
32 std::vector<Ptr<Vector<Real>>> iterDiff; // Step Storage
33 std::vector<Ptr<Vector<Real>>> gradDiff; // Gradient Storage
34 std::vector<Real> product; // Step-Gradient Inner Product Storage
35 std::vector<Real> product2; // Step-Gradient Inner Product Storage
36 int storage; // Storage Size
37 int current; // Current Storage Size
38 int iter; // Current Optimization Iteration
39 ESecantMode mode; // Intended application mode
40
41 SecantState(int M, ESecantMode sm) : storage(M), current(-1), iter(0), mode(sm) {}
42};
43
44template<class Real>
45class Secant : public LinearOperator<Real> {
46protected:
47
48 const Ptr<SecantState<Real>> state_; // Secant State
49 Ptr<Vector<Real>> y_;
52
53private:
54
56
57public:
58
59 virtual ~Secant() {}
60
61 // Constructor
62 Secant( int M = 10, bool useDefaultScaling = true, Real Bscaling = Real(1), ESecantMode mode = SECANTMODE_BOTH )
63 : state_(makePtr<SecantState<Real>>(M,mode)),
64 useDefaultScaling_(useDefaultScaling), Bscaling_(Bscaling),
65 isInitialized_(false) {}
66
67 Ptr<SecantState<Real>>& get_state() { return state_; }
68 const Ptr<SecantState<Real>>& get_state() const { return state_; }
69
70 // Update Secant Approximation
71 virtual void updateStorage( const Vector<Real> &x, const Vector<Real> &grad,
72 const Vector<Real> &gp, const Vector<Real> &s,
73 const Real snorm, const int iter ) {
74 const Real one(1);
75 if ( !isInitialized_ ) {
76 state_->iterate = x.clone();
77 y_ = grad.clone();
78 isInitialized_ = true;
79 }
80 state_->iterate->set(x);
81 state_->iter = iter;
82 y_->set(grad);
83 y_->axpy(-one,gp);
84
85 //Real sy = s.dot(y_->dual());
86 Real sy = s.apply(*y_);
87 if (sy > ROL_EPSILON<Real>()*snorm*snorm) {
88 if (state_->current < state_->storage-1) {
89 state_->current++; // Increment Storage
90 state_->iterDiff.push_back(s.clone()); // Create new memory
91 state_->gradDiff.push_back(grad.clone()); // Create new memory
92 }
93 else {
94 state_->iterDiff.push_back(state_->iterDiff[0]); // Move first element to the last
95 state_->gradDiff.push_back(state_->gradDiff[0]); // Move first element to the last
96 state_->iterDiff.erase(state_->iterDiff.begin()); // Remove first element of s list
97 state_->gradDiff.erase(state_->gradDiff.begin()); // Remove first element of y list
98 state_->product.erase(state_->product.begin()); // Remove first element of rho list
99 }
100 state_->iterDiff[state_->current]->set(s); // s=x_{k+1}-x_k
101 state_->gradDiff[state_->current]->set(*y_); // y=g_{k+1}-g_k
102 state_->product.push_back(sy); // ys=1/rho
103 }
104 }
105
106 // Apply Secant Approximate Inverse Hessian
107 virtual void applyH( Vector<Real> &Hv, const Vector<Real> &v ) const = 0;
108
109 // Apply Initial Secant Approximate Inverse Hessian
110 virtual void applyH0( Vector<Real> &Hv, const Vector<Real> &v ) const {
111 Hv.set(v.dual());
112 if (useDefaultScaling_) {
113 if (state_->iter != 0 && state_->current != -1) {
114 Real yy = state_->gradDiff[state_->current]->dot(*(state_->gradDiff[state_->current]));
115 Hv.scale(state_->product[state_->current]/yy);
116 }
117 }
118 else {
119 Hv.scale(static_cast<Real>(1)/Bscaling_);
120 }
121 }
122
123 // Apply Secant Approximate Hessian
124 virtual void applyB( Vector<Real> &Bv, const Vector<Real> &v ) const = 0;
125
126 // Apply Initial Secant Approximate Hessian
127 virtual void applyB0( Vector<Real> &Bv, const Vector<Real> &v ) const {
128 Bv.set(v.dual());
129 if (useDefaultScaling_) {
130 if (state_->iter != 0 && state_->current != -1) {
131 Real yy = state_->gradDiff[state_->current]->dot(*(state_->gradDiff[state_->current]));
132 Bv.scale(yy/state_->product[state_->current]);
133 }
134 }
135 else {
136 Bv.scale(Bscaling_);
137 }
138 }
139
140 // Test Secant Approximations
141 void test(std::ostream &stream = std::cout ) const {
142 if (isInitialized_) {
143 Ptr<Vector<Real>> v = state_->iterate->clone();
144 Ptr<Vector<Real>> Hv = state_->iterate->clone();
145 Ptr<Vector<Real>> Bv = state_->iterate->dual().clone();
146 const Real one(1);
147
148 // Print BHv -> Should be v
149 v->randomize(-one,one);
150 applyH(*Hv,*v);
151 applyB(*Bv,*Hv);
152 v->axpy(-one,*Bv);
153 stream << " ||BHv-v|| = " << v->norm() << std::endl;
154
155 // Print HBv -> Should be v
156 v->randomize(-one,one);
157 applyB(*Bv,*v);
158 applyH(*Hv,*Bv);
159 v->axpy(-one,*Hv);
160 stream << " ||HBv-v|| = " << v->norm() << std::endl;
161 }
162 }
163
164 void apply(Vector<Real> &Hv, const Vector<Real> &v, Real &tol) const {
165 applyB(Hv,v);
166 }
167
168 void applyInverse(Vector<Real> &Hv, const Vector<Real> &v, Real &tol) const {
169 applyH(Hv,v);
170 }
171
172};
173
174}
175
176#include "ROL_SecantFactory.hpp"
177
178#endif
Contains definitions of custom data types in ROL.
Provides the interface to apply a linear operator.
Provides interface for and implements limited-memory secant operators.
virtual void applyB0(Vector< Real > &Bv, const Vector< Real > &v) const
virtual void applyB(Vector< Real > &Bv, const Vector< Real > &v) const =0
Ptr< SecantState< Real > > & get_state()
virtual void applyH0(Vector< Real > &Hv, const Vector< Real > &v) const
bool isInitialized_
bool useDefaultScaling_
void applyInverse(Vector< Real > &Hv, const Vector< Real > &v, Real &tol) const
Apply inverse of linear operator.
void test(std::ostream &stream=std::cout) const
Secant(int M=10, bool useDefaultScaling=true, Real Bscaling=Real(1), ESecantMode mode=SECANTMODE_BOTH)
void apply(Vector< Real > &Hv, const Vector< Real > &v, Real &tol) const
Apply linear operator.
const Ptr< SecantState< Real > > & get_state() const
const Ptr< SecantState< Real > > state_
virtual ~Secant()
virtual void updateStorage(const Vector< Real > &x, const Vector< Real > &grad, const Vector< Real > &gp, const Vector< Real > &s, const Real snorm, const int iter)
virtual void applyH(Vector< Real > &Hv, const Vector< Real > &v) const =0
Ptr< Vector< Real > > y_
Defines the linear algebra or vector space interface.
virtual Real apply(const Vector< Real > &x) const
Apply to a dual vector. This is equivalent to the call .
virtual void set(const Vector &x)
Set where .
virtual void scale(const Real alpha)=0
Compute where .
virtual const Vector & dual() const
Return dual representation of , for example, the result of applying a Riesz map, or change of basis,...
virtual ROL::Ptr< Vector > clone() const =0
Clone to make a new (uninitialized) vector.
ESecantMode
@ SECANTMODE_FORWARD
@ SECANTMODE_INVERSE
@ SECANTMODE_BOTH
Ptr< Vector< Real > > iterate
std::vector< Ptr< Vector< Real > > > iterDiff
SecantState(int M, ESecantMode sm)
std::vector< Real > product
ESecantMode mode
std::vector< Real > product2
std::vector< Ptr< Vector< Real > > > gradDiff