ROL
ROL_FletcherObjectiveE_Def.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_FLETCHEROBJECTIVEEDEF_H
11#define ROL_FLETCHEROBJECTIVEEDEF_H
12
13namespace ROL {
14
15template<typename Real>
17 const ROL::Ptr<Constraint<Real>> &con,
18 const Vector<Real> &xprim,
19 const Vector<Real> &xdual,
20 const Vector<Real> &cprim,
21 const Vector<Real> &cdual,
22 ROL::ParameterList &parlist)
23 : FletcherObjectiveBase<Real>(obj, con, xprim, xdual, cprim, cdual, parlist) {
24 Tv_ = xdual.clone();
25 w_ = xdual.clone();
26 wdual_ = xprim.clone();
27 v_ = cdual.clone();
28 wg_ = xdual.clone();
29 vg_ = cdual.clone();
30
31 xzeros_ = xdual.clone(); xzeros_->zero();
32 czeros_ = cprim.clone(); czeros_->zero();
33}
34
35template<typename Real>
36Real FletcherObjectiveE<Real>::value( const Vector<Real> &x, Real &tol ) {
37 Real val(0);
38 int key(0);
39 bool isComputed = fPhi_->get(val,key);
40 if( isComputed && multSolverError_*cnorm_ <= tol) {
41 tol = multSolverError_*cnorm_;
42 }
43 else {
44 // Reset tolerances
45 Real origTol = tol;
46 Real tol2 = origTol;
47 // Compute penalty function value
48 Real fval = FletcherObjectiveBase<Real>::objValue(x, tol2); tol2 = origTol;
49 multSolverError_ = origTol / (static_cast<Real>(2) * std::max(static_cast<Real>(1), cnorm_));
50 FletcherObjectiveBase<Real>::computeMultipliers(*cdual_, *gLdual_, x, *xdual_, *cprim_, multSolverError_);
51 tol = multSolverError_*cnorm_;
52 //val = fval - cprim_->dot(cdual_->dual());
53 val = fval - cprim_->apply(*cdual_);
54 if( quadPenaltyParameter_ > static_cast<Real>(0) )
55 val += static_cast<Real>(0.5)*quadPenaltyParameter_*(cprim_->dot(*cprim_));
56 // Store new penalty function value
57 fPhi_->set(val,key);
58 }
59 return val;
60}
61
62template<typename Real>
64 int key(0);
65 bool isComputed = gPhi_->get(g,key);
66 if( isComputed && gradSolveError_ <= tol) {
67 tol = gradSolveError_;
68 }
69 else {
70 // Reset tolerances
71 Real origTol = tol;
72 Real tol2 = origTol;
73 // Compute penalty function gradient
74 gradSolveError_ = origTol / static_cast<Real>(2);
75 FletcherObjectiveBase<Real>::computeMultipliers(*cdual_, *gLdual_, x, *xdual_, *cprim_, gradSolveError_);
76 gL_->set(gLdual_->dual());
77 bool refine = isComputed;
78 // gPhi = sum y_i H_i w + sigma w + sum v_i H_i gL - H w + gL
79 solveAugmentedSystem( *wdual_, *vg_, *xzeros_, *cprim_, x, gradSolveError_, refine );
80 gradSolveError_ += multSolverError_;
81 tol = gradSolveError_;
82 wg_->set(wdual_->dual());
83 con_->applyAdjointHessian( g, *cdual_, *wdual_, x, tol2 ); tol2 = origTol;
84 g.axpy( sigma_, *wg_ );
85 obj_->hessVec( *Tv_, *wdual_, x, tol2 ); tol2 = origTol;
86 g.axpy( static_cast<Real>(-1), *Tv_ );
87 con_->applyAdjointHessian( *Tv_, *vg_, *gLdual_, x, tol2 ); tol2 = origTol;
88 g.plus( *Tv_ );
89 g.plus( *gL_ );
90 if( quadPenaltyParameter_ > static_cast<Real>(0) ) {
91 con_->applyAdjointJacobian( *Tv_, *cprim_, x, tol2 ); tol2 = origTol;
92 g.axpy( quadPenaltyParameter_, *Tv_ );
93 }
94 gPhi_->set(g,key);
95 }
96}
97
98template<typename Real>
99void FletcherObjectiveE<Real>::hessVec( Vector<Real> &hv, const Vector<Real> &v, const Vector<Real> &x, Real &tol ) {
100 // Reset tolerances
101 Real origTol = tol;
102 Real tol2 = origTol;
103 int key(0);
104 bool isComputed = y_->get(*cdual_,key);
105 if( !isComputed || !useInexact_) {
106 // hessVec tol is always set to ~1e-8. So if inexact linear system solves are used, then
107 // the multipliers will always get re-evaluated to high precision, which defeats the purpose
108 // of computing the objective/gradient approximately.
109 // Thus if inexact linear system solves are used, we will not update the multiplier estimates
110 // to high precision.
111 FletcherObjectiveBase<Real>::computeMultipliers(*cdual_, *gLdual_, x, *xdual_, *cprim_, tol);
112 }
113
114 obj_->hessVec( hv, v, x, tol2 ); tol2 = origTol;
115 con_->applyAdjointHessian( *Tv_, *cdual_, v, x, tol2 ); tol2 = origTol;
116 hv.axpy(static_cast<Real>(-1), *Tv_ );
117
118 tol2 = tol;
119 solveAugmentedSystem( *w_, *v_, hv, *czeros_, x, tol2 ); tol2 = origTol;
120 hv.scale( static_cast<Real>(-1) );
121 hv.plus( *w_ );
122
123 Tv_->set(v.dual());
124 tol2 = tol;
125 solveAugmentedSystem( *w_, *v_, *Tv_, *czeros_, x, tol2 ); tol2 = origTol;
126 hv.axpy(static_cast<Real>(-2)*sigma_, *w_);
127
128 wdual_->set(w_->dual());
129
130 obj_->hessVec( *Tv_, *wdual_, x, tol2 ); tol2 = origTol;
131 hv.plus( *Tv_ );
132 con_->applyAdjointHessian( *Tv_, *cdual_, *wdual_, x, tol2 ); tol2 = origTol;
133 hv.axpy( static_cast<Real>(-1), *Tv_ );
134
135 hv.axpy( static_cast<Real>(2)*sigma_, v );
136
137 if( quadPenaltyParameter_ > static_cast<Real>(0) ) {
138 con_->applyJacobian( *b2_, v, x, tol2 ); tol2 = origTol;
139 con_->applyAdjointJacobian( *Tv_, *b2_, x, tol2 ); tol2 = origTol;
140 hv.axpy( quadPenaltyParameter_, *Tv_ );
141 con_->applyAdjointHessian( *Tv_, *cprim_, v, x, tol2); tol2 = origTol;
142 hv.axpy( -quadPenaltyParameter_, *Tv_ );
143 }
144}
145
146template<typename Real>
148 Vector<Real> &v2,
149 const Vector<Real> &b1,
150 const Vector<Real> &b2,
151 const Vector<Real> &x,
152 Real &tol,
153 bool refine) {
154 // Ignore tol for now
155 ROL::Ptr<LinearOperator<Real>>
156 K = ROL::makePtr<AugSystem>(con_, makePtrFromRef(x), delta_);
157 ROL::Ptr<LinearOperator<Real>>
158 P = ROL::makePtr<AugSystemPrecond>(con_, makePtrFromRef(x), makePtrFromRef(b1));
159
160 vv_->zero();
161 bb_->zero();
162 if( refine ) {
163 // TODO: Make sure this tol is actually ok...
164 Real origTol = tol;
165 w1_->set(v1);
166 w2_->set(v2);
167 K->apply(*bb_, *ww_, tol); tol = origTol;
168 bb_->scale(static_cast<Real>(-1));
169 }
170 b1_->plus(b1);
171 b2_->plus(b2);
172
173 // If inexact, change tolerance
174 if( useInexact_ ) krylov_->resetAbsoluteTolerance(tol);
175
176 //con_->solveAugmentedSystem(*v1_,*v2_,*b1_,*b2_,x,tol);
177 flagKrylov_ = 0;
178 tol = krylov_->run(*vv_,*K,*bb_,*P,iterKrylov_,flagKrylov_);
179
180 if( refine ) {
181 v1.plus(*v1_);
182 v2.plus(*v2_);
183 } else {
184 v1.set(*v1_);
185 v2.set(*v2_);
186 }
187}
188
189} // namespace ROL
190
191#endif
const Ptr< Obj > obj_
Defines the general constraint operator interface.
Real objValue(const Vector< Real > &x, Real &tol)
void computeMultipliers(Vector< Real > &y, Vector< Real > &gL, const Vector< Real > &x, Vector< Real > &g, Vector< Real > &c, Real tol)
void solveAugmentedSystem(Vector< Real > &v1, Vector< Real > &v2, const Vector< Real > &b1, const Vector< Real > &b2, const Vector< Real > &x, Real &tol, bool refine=false) override
void hessVec(Vector< Real > &hv, const Vector< Real > &v, const Vector< Real > &x, Real &tol) override
Apply Hessian approximation to vector.
void gradient(Vector< Real > &g, const Vector< Real > &x, Real &tol) override
Compute gradient.
Real value(const Vector< Real > &x, Real &tol) override
Compute value.
FletcherObjectiveE(const ROL::Ptr< Objective< Real > > &obj, const ROL::Ptr< Constraint< Real > > &con, const Vector< Real > &xprim, const Vector< Real > &xdual, const Vector< Real > &cprim, const Vector< Real > &cdual, ROL::ParameterList &parlist)
Provides the interface to evaluate objective functions.
Defines the linear algebra or vector space interface.
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 void plus(const Vector &x)=0
Compute , where .
virtual ROL::Ptr< Vector > clone() const =0
Clone to make a new (uninitialized) vector.
virtual void axpy(const Real alpha, const Vector &x)
Compute where .