ROL
ROL_Bundle_AS.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_BUNDLE_AS_H
11#define ROL_BUNDLE_AS_H
12
13#include "ROL_Bundle.hpp"
14
19namespace ROL {
20
21template<class Real>
22class Bundle_AS : public Bundle<Real> {
23/***********************************************************************************************/
24/***************** BUNDLE STORAGE **************************************************************/
25/***********************************************************************************************/
26private:
27
28 ROL::Ptr<Vector<Real> > tG_;
29 ROL::Ptr<Vector<Real> > eG_;
30 ROL::Ptr<Vector<Real> > yG_;
31 ROL::Ptr<Vector<Real> > gx_;
32 ROL::Ptr<Vector<Real> > ge_;
33
34 std::set<unsigned> workingSet_;
35 std::set<unsigned> nworkingSet_;
36
38
39/***********************************************************************************************/
40/***************** BUNDLE MODIFICATION AND ACCESS ROUTINES *************************************/
41/***********************************************************************************************/
42public:
43 Bundle_AS(const unsigned maxSize = 10,
44 const Real coeff = 0.0,
45 const Real omega = 2.0,
46 const unsigned remSize = 2)
47 : Bundle<Real>(maxSize,coeff,omega,remSize), isInitialized_(false) {}
48
49 void initialize(const Vector<Real> &g) {
51 if ( !isInitialized_ ) {
52 tG_ = g.clone();
53 yG_ = g.clone();
54 eG_ = g.clone();
55 gx_ = g.clone();
56 ge_ = g.clone();
57 isInitialized_ = true;
58 }
59 }
60
61 unsigned solveDual(const Real t, const unsigned maxit = 1000, const Real tol = 1.e-8) {
62 unsigned iter = 0;
63 if (Bundle<Real>::size() == 1) {
64 iter = Bundle<Real>::solveDual_dim1(t,maxit,tol);
65 }
66 else if (Bundle<Real>::size() == 2) {
67 iter = Bundle<Real>::solveDual_dim2(t,maxit,tol);
68 }
69 else {
70 iter = solveDual_arbitrary(t,maxit,tol);
71 }
72 return iter;
73 }
74
75/***********************************************************************************************/
76/***************** DUAL CUTTING PLANE PROBLEM ROUTINES *****************************************/
77/***********************************************************************************************/
78private:
80 Real sum(0), err(0), tmp(0), y(0), zero(0);
81 for (unsigned i = 0; i < Bundle<Real>::size(); ++i) {
82 // Compute sum of dualVariables_ using Kahan's compensated sum
83 //sum += Bundle<Real>::getDualVariable(i);
85 tmp = sum + y;
86 err = (tmp - sum) - y;
87 sum = tmp;
88 }
89 for (unsigned i = 0; i < Bundle<Real>::size(); ++i) {
92 }
93 nworkingSet_.clear();
94 workingSet_.clear();
95 for (unsigned i = 0; i < Bundle<Real>::size(); ++i) {
97 workingSet_.insert(i);
98 }
99 else {
100 nworkingSet_.insert(i);
101 }
102 }
103 }
104
105 void computeLagMult(std::vector<Real> &lam, const Real mu, const std::vector<Real> &g) const {
106 Real zero(0);
107 unsigned n = workingSet_.size();
108 if ( n > 0 ) {
109 lam.resize(n,zero);
110 typename std::set<unsigned>::iterator it = workingSet_.begin();
111 for (unsigned i = 0; i < n; ++i) {
112 lam[i] = g[*it] - mu; it++;
113 }
114 }
115 else {
116 lam.clear();
117 }
118 }
119
120 bool isNonnegative(unsigned &ind, const std::vector<Real> &x) const {
121 bool flag = true;
122 unsigned n = workingSet_.size(); ind = Bundle<Real>::size();
123 if ( n > 0 ) {
124 Real min = ROL_OVERFLOW<Real>();
125 typename std::set<unsigned>::iterator it = workingSet_.begin();
126 for (unsigned i = 0; i < n; ++i) {
127 if ( x[i] < min ) {
128 ind = *it;
129 min = x[i];
130 }
131 it++;
132 }
133 flag = ((min < -ROL_EPSILON<Real>()) ? false : true);
134 }
135 return flag;
136 }
137
138 Real computeStepSize(unsigned &ind, const std::vector<Real> &x, const std::vector<Real> &p) const {
139 Real alpha(1), tmp(0), zero(0); ind = Bundle<Real>::size();
140 typename std::set<unsigned>::iterator it;
141 for (it = nworkingSet_.begin(); it != nworkingSet_.end(); it++) {
142 if ( p[*it] < -ROL_EPSILON<Real>() ) {
143 tmp = -x[*it]/p[*it];
144 if ( alpha >= tmp ) {
145 alpha = tmp;
146 ind = *it;
147 }
148 }
149 }
150 return std::max(zero,alpha);
151 }
152
153 unsigned solveEQPsubproblem(std::vector<Real> &s, Real &mu,
154 const std::vector<Real> &g, const Real tol) const {
155 // Build reduced QP information
156 Real zero(0);
157 unsigned n = nworkingSet_.size(), cnt = 0;
158 mu = zero;
159 s.assign(Bundle<Real>::size(),zero);
160 if ( n > 0 ) {
161 std::vector<Real> gk(n,zero);
162 typename std::set<unsigned>::iterator it = nworkingSet_.begin();
163 for (unsigned i = 0; i < n; ++i) {
164 gk[i] = g[*it]; it++;
165 }
166 std::vector<Real> sk(n,zero);
167 cnt = projectedCG(sk,mu,gk,tol);
168 it = nworkingSet_.begin();
169 for (unsigned i = 0; i < n; ++i) {
170 s[*it] = sk[i]; it++;
171 }
172 }
173 return cnt;
174 }
175
176 void applyPreconditioner(std::vector<Real> &Px, const std::vector<Real> &x) const {
177 Real zero(0);
178 int type = 0;
179 std::vector<Real> tmp(Px.size(),zero);
180 switch (type) {
181 case 0: applyPreconditioner_Identity(tmp,x); break;
182 case 1: applyPreconditioner_Jacobi(tmp,x); break;
183 case 2: applyPreconditioner_SymGS(tmp,x); break;
184 }
186 }
187
188 void applyG(std::vector<Real> &Gx, const std::vector<Real> &x) const {
189 int type = 0;
190 switch (type) {
191 case 0: applyG_Identity(Gx,x); break;
192 case 1: applyG_Jacobi(Gx,x); break;
193 case 2: applyG_SymGS(Gx,x); break;
194 }
195 }
196
197 void applyPreconditioner_Identity(std::vector<Real> &Px, const std::vector<Real> &x) const {
198 unsigned dim = nworkingSet_.size();
199 Real sum(0), err(0), tmp(0), y(0);
200 for (unsigned i = 0; i < dim; ++i) {
201 // Compute sum of x using Kahan's compensated sum
202 //sum += x[i];
203 y = x[i] - err;
204 tmp = sum + y;
205 err = (tmp - sum) - y;
206 sum = tmp;
207 }
208 sum /= (Real)dim;
209 for (unsigned i = 0; i < dim; ++i) {
210 Px[i] = x[i] - sum;
211 }
212 }
213
214 void applyG_Identity(std::vector<Real> &Gx, const std::vector<Real> &x) const {
215 Gx.assign(x.begin(),x.end());
216 }
217
218 void applyPreconditioner_Jacobi(std::vector<Real> &Px, const std::vector<Real> &x) const {
219 unsigned dim = nworkingSet_.size();
220 Real eHe(0), sum(0), one(1), zero(0);
221 Real errX(0), tmpX(0), yX(0), errE(0), tmpE(0), yE(0);
222 std::vector<Real> gg(dim,zero);
223 typename std::set<unsigned>::iterator it = nworkingSet_.begin();
224 for (unsigned i = 0; i < dim; ++i) {
225 gg[i] = one/std::abs(Bundle<Real>::GiGj(*it,*it)); it++;
226 // Compute sum of inv(D)x using Kahan's aggregated sum
227 //sum += x[i]*gg[i];
228 yX = x[i]*gg[i] - errX;
229 tmpX = sum + yX;
230 errX = (tmpX - sum) - yX;
231 sum = tmpX;
232 // Compute sum of inv(D)e using Kahan's aggregated sum
233 //eHe += gg[i];
234 yE = gg[i] - errE;
235 tmpE = eHe + yE;
236 errE = (tmpE - eHe) - yE;
237 eHe = tmpE;
238 }
239 sum /= eHe;
240 for (unsigned i = 0; i < dim; ++i) {
241 Px[i] = (x[i]-sum)*gg[i];
242 }
243 }
244
245 void applyG_Jacobi(std::vector<Real> &Gx, const std::vector<Real> &x) const {
246 unsigned dim = nworkingSet_.size();
247 typename std::set<unsigned>::iterator it = nworkingSet_.begin();
248 for (unsigned i = 0; i < dim; ++i) {
249 Gx[i] = std::abs(Bundle<Real>::GiGj(*it,*it))*x[i]; it++;
250 }
251 }
252
253 void applyPreconditioner_SymGS(std::vector<Real> &Px, const std::vector<Real> &x) const {
254 int dim = nworkingSet_.size();
255 //unsigned cnt = 0;
256 gx_->zero(); ge_->zero();
257 Real eHx(0), eHe(0), one(1);
258 // Forward substitution
259 std::vector<Real> x1(dim,0), e1(dim,0),gg(dim,0);
260 typename std::set<unsigned>::iterator it, jt;
261 it = nworkingSet_.begin();
262 for (int i = 0; i < dim; ++i) {
263 gx_->zero(); ge_->zero(); jt = nworkingSet_.begin();
264 for (int j = 0; j < i; ++j) {
265 Bundle<Real>::addGi(*jt,x1[j],*gx_);
266 Bundle<Real>::addGi(*jt,e1[j],*ge_);
267 jt++;
268 }
269 gg[i] = Bundle<Real>::GiGj(*it,*it);
270 x1[i] = (x[i] - Bundle<Real>::dotGi(*it,*gx_))/gg[i];
271 e1[i] = (one - Bundle<Real>::dotGi(*it,*ge_))/gg[i];
272 it++;
273 }
274 // Apply diagonal
275 for (int i = 0; i < dim; ++i) {
276 x1[i] *= gg[i];
277 e1[i] *= gg[i];
278 }
279 // Back substitution
280 std::vector<Real> Hx(dim,0), He(dim,0); it = nworkingSet_.end();
281 for (int i = dim-1; i >= 0; --i) {
282 it--;
283 gx_->zero(); ge_->zero(); jt = nworkingSet_.end();
284 for (int j = dim-1; j >= i+1; --j) {
285 jt--;
286 Bundle<Real>::addGi(*jt,Hx[j],*gx_);
287 Bundle<Real>::addGi(*jt,He[j],*ge_);
288 }
289 Hx[i] = (x1[i] - Bundle<Real>::dotGi(*it,*gx_))/gg[i];
290 He[i] = (e1[i] - Bundle<Real>::dotGi(*it,*ge_))/gg[i];
291 // Compute sums
292 eHx += Hx[i];
293 eHe += He[i];
294 }
295 // Accumulate preconditioned vector
296 for (int i = 0; i < dim; ++i) {
297 Px[i] = Hx[i] - (eHx/eHe)*He[i];
298 }
299 }
300
301 void applyG_SymGS(std::vector<Real> &Gx, const std::vector<Real> &x) const {
302 unsigned dim = nworkingSet_.size();
303 typename std::set<unsigned>::iterator it = nworkingSet_.begin();
304 for (unsigned i = 0; i < dim; ++i) {
305 Gx[i] = std::abs(Bundle<Real>::GiGj(*it,*it))*x[i]; it++;
306 }
307 }
308
309 void computeResidualUpdate(std::vector<Real> &r, std::vector<Real> &g) const {
310 unsigned n = g.size();
311 std::vector<Real> Gg(n,0);
312 Real y(0), ytmp(0), yprt(0), yerr(0);
314 applyG(Gg,g);
315 // Compute multiplier using Kahan's compensated sum
316 for (unsigned i = 0; i < n; ++i) {
317 //y += (r[i] - Gg[i]);
318 yprt = (r[i] - Gg[i]) - yerr;
319 ytmp = y + yprt;
320 yerr = (ytmp - y) - yprt;
321 y = ytmp;
322 }
323 y /= (Real)n;
324 for (unsigned i = 0; i < n; ++i) {
325 r[i] -= y;
326 }
328 }
329
330 void applyFullMatrix(std::vector<Real> &Hx, const std::vector<Real> &x) const {
331 Real one(1);
332 gx_->zero(); eG_->zero();
333 for (unsigned i = 0; i < Bundle<Real>::size(); ++i) {
334 // Compute Gx using Kahan's compensated sum
335 //gx_->axpy(x[i],Bundle<Real>::subgradient(i));
336 yG_->set(Bundle<Real>::subgradient(i)); yG_->scale(x[i]); yG_->axpy(-one,*eG_);
337 tG_->set(*gx_); tG_->plus(*yG_);
338 eG_->set(*tG_); eG_->axpy(-one,*gx_); eG_->axpy(-one,*yG_);
339 gx_->set(*tG_);
340 }
341 for (unsigned i = 0; i < Bundle<Real>::size(); ++i) {
342 // Compute < g_i, Gx >
343 Hx[i] = Bundle<Real>::dotGi(i,*gx_);
344 }
345 }
346
347 void applyMatrix(std::vector<Real> &Hx, const std::vector<Real> &x) const {
348 Real one(1);
349 gx_->zero(); eG_->zero();
350 unsigned n = nworkingSet_.size();
351 typename std::set<unsigned>::iterator it = nworkingSet_.begin();
352 for (unsigned i = 0; i < n; ++i) {
353 // Compute Gx using Kahan's compensated sum
354 //gx_->axpy(x[i],Bundle<Real>::subgradient(*it));
355 yG_->set(Bundle<Real>::subgradient(*it)); yG_->scale(x[i]); yG_->axpy(-one,*eG_);
356 tG_->set(*gx_); tG_->plus(*yG_);
357 eG_->set(*tG_); eG_->axpy(-one,*gx_); eG_->axpy(-one,*yG_);
358 gx_->set(*tG_);
359 it++;
360 }
361 it = nworkingSet_.begin();
362 for (unsigned i = 0; i < n; ++i) {
363 // Compute < g_i, Gx >
364 Hx[i] = Bundle<Real>::dotGi(*it,*gx_); it++;
365 }
366 }
367
368 unsigned projectedCG(std::vector<Real> &x, Real &mu, const std::vector<Real> &b, const Real tol) const {
369 Real one(1), zero(0);
370 unsigned n = nworkingSet_.size();
371 std::vector<Real> r(n,0), r0(n,0), g(n,0), d(n,0), Ad(n,0);
372 // Compute residual Hx + g = g with x = 0
373 x.assign(n,0);
374 scale(r,one,b);
375 r0.assign(r.begin(),r.end());
376 // Precondition residual
378 Real rg = dot(r,g), rg0(0);
379 // Get search direction
380 scale(d,-one,g);
381 Real alpha(0), kappa(0), beta(0), TOL(1.e-2);
382 Real CGtol = std::min(tol,TOL*rg);
383 unsigned cnt = 0;
384 while (rg > CGtol && cnt < 2*n+1) {
385 applyMatrix(Ad,d);
386 kappa = dot(d,Ad);
387 alpha = rg/kappa;
388 axpy(alpha,d,x);
389 axpy(alpha,Ad,r);
390 axpy(alpha,Ad,r0);
392 rg0 = rg;
393 rg = dot(r,g);
394 beta = rg/rg0;
395 scale(d,beta);
396 axpy(-one,g,d);
397 cnt++;
398 }
399 // Compute multiplier for equality constraint using Kahan's compensated sum
400 mu = zero;
401 Real err(0), tmp(0), y(0);
402 for (unsigned i = 0; i < n; ++i) {
403 //mu += r0[i];
404 y = r0[i] - err;
405 tmp = mu + y;
406 err = (tmp - mu) - y;
407 mu = tmp;
408 }
409 mu /= static_cast<Real>(n);
410 // Return iteration count
411 return cnt;
412 }
413
414 Real dot(const std::vector<Real> &x, const std::vector<Real> &y) const {
415 // Compute dot product of two vectors using Kahan's compensated sum
416 Real val(0), err(0), tmp(0), y0(0);
417 unsigned n = std::min(x.size(),y.size());
418 for (unsigned i = 0; i < n; ++i) {
419 //val += x[i]*y[i];
420 y0 = x[i]*y[i] - err;
421 tmp = val + y0;
422 err = (tmp - val) - y0;
423 val = tmp;
424 }
425 return val;
426 }
427
428 Real norm(const std::vector<Real> &x) const {
429 return std::sqrt(dot(x,x));
430 }
431
432 void axpy(const Real a, const std::vector<Real> &x, std::vector<Real> &y) const {
433 unsigned n = std::min(y.size(),x.size());
434 for (unsigned i = 0; i < n; ++i) {
435 y[i] += a*x[i];
436 }
437 }
438
439 void scale(std::vector<Real> &x, const Real a) const {
440 for (unsigned i = 0; i < x.size(); ++i) {
441 x[i] *= a;
442 }
443 }
444
445 void scale(std::vector<Real> &x, const Real a, const std::vector<Real> &y) const {
446 unsigned n = std::min(x.size(),y.size());
447 for (unsigned i = 0; i < n; ++i) {
448 x[i] = a*y[i];
449 }
450 }
451
452 unsigned solveDual_arbitrary(const Real t, const unsigned maxit = 1000, const Real tol = 1.e-8) {
454 bool nonneg = false;
455 unsigned ind = 0, i = 0, CGiter = 0;
456 Real snorm(0), alpha(0), mu(0), one(1), zero(0);
457 std::vector<Real> s(Bundle<Real>::size(),0), Hs(Bundle<Real>::size(),0);
458 std::vector<Real> g(Bundle<Real>::size(),0), lam(Bundle<Real>::size()+1,0);
459 std::vector<Real> dualVariables(Bundle<Real>::size(),0);
460 for (unsigned j = 0; j < Bundle<Real>::size(); ++j) {
461 dualVariables[j] = Bundle<Real>::getDualVariable(j);
462 }
463 //Real val = Bundle<Real>::evaluateObjective(g,dualVariables,t);
464 Bundle<Real>::evaluateObjective(g,dualVariables,t);
465 for (i = 0; i < maxit; ++i) {
466 CGiter += solveEQPsubproblem(s,mu,g,tol);
467 snorm = norm(s);
468 if ( snorm < ROL_EPSILON<Real>() ) {
469 computeLagMult(lam,mu,g);
470 nonneg = isNonnegative(ind,lam);
471 if ( nonneg ) {
472 break;
473 }
474 else {
475 alpha = one;
476 if ( ind < Bundle<Real>::size() ) {
477 workingSet_.erase(ind);
478 nworkingSet_.insert(ind);
479 }
480 }
481 }
482 else {
483 alpha = computeStepSize(ind,dualVariables,s);
484 if ( alpha > zero ) {
485 axpy(alpha,s,dualVariables);
486 applyFullMatrix(Hs,s);
487 axpy(alpha,Hs,g);
488 }
489 if (ind < Bundle<Real>::size()) {
490 workingSet_.insert(ind);
491 nworkingSet_.erase(ind);
492 }
493 }
494 //std::cout << "iter = " << i << " snorm = " << snorm << " alpha = " << alpha << "\n";
495 }
496 //Real crit = computeCriticality(g,dualVariables);
497 //std::cout << "Criticality Measure: " << crit << "\n";
498 //std::cout << "dim = " << Bundle<Real>::size() << " iter = " << i << " CGiter = " << CGiter << " CONVERGED!\n";
499 for (unsigned j = 0; j < Bundle<Real>::size(); ++j) {
500 Bundle<Real>::setDualVariable(j,dualVariables[j]);
501 }
502 return i;
503 }
504
505 /************************************************************************/
506 /********************** PROJECTION ONTO FEASIBLE SET ********************/
507 /************************************************************************/
508 void project(std::vector<Real> &x, const std::vector<Real> &v) const {
509 std::vector<Real> vsort(Bundle<Real>::size(),0);
510 vsort.assign(v.begin(),v.end());
511 std::sort(vsort.begin(),vsort.end());
512 Real sum(-1), lam(0), zero(0), one(1);
513 for (unsigned i = Bundle<Real>::size()-1; i > 0; i--) {
514 sum += vsort[i];
515 if ( sum >= static_cast<Real>(Bundle<Real>::size()-i)*vsort[i-1] ) {
516 lam = sum/static_cast<Real>(Bundle<Real>::size()-i);
517 break;
518 }
519 }
520 if (lam == zero) {
521 lam = (sum+vsort[0])/static_cast<Real>(Bundle<Real>::size());
522 }
523 for (unsigned i = 0; i < Bundle<Real>::size(); ++i) {
524 x[i] = std::max(zero,v[i] - lam);
525 }
526 }
527
528 Real computeCriticality(const std::vector<Real> &g, const std::vector<Real> &sol) {
529 Real zero(0), one(1);
530 std::vector<Real> x(Bundle<Real>::size(),0), Px(Bundle<Real>::size(),0);
531 axpy(one,sol,x);
532 axpy(-one,g,x);
533 project(Px,x);
534 scale(x,zero);
535 axpy(one,sol,x);
536 axpy(-one,Px,x);
537 return norm(x);
538 }
539}; // class Bundle_AS
540
541} // namespace ROL
542
543#endif
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
Provides the interface for and implements an active set bundle.
void scale(std::vector< Real > &x, const Real a, const std::vector< Real > &y) const
void applyPreconditioner_Jacobi(std::vector< Real > &Px, const std::vector< Real > &x) const
ROL::Ptr< Vector< Real > > gx_
void axpy(const Real a, const std::vector< Real > &x, std::vector< Real > &y) const
Real computeCriticality(const std::vector< Real > &g, const std::vector< Real > &sol)
void applyMatrix(std::vector< Real > &Hx, const std::vector< Real > &x) const
void scale(std::vector< Real > &x, const Real a) const
void applyG_Identity(std::vector< Real > &Gx, const std::vector< Real > &x) const
std::set< unsigned > nworkingSet_
unsigned solveDual_arbitrary(const Real t, const unsigned maxit=1000, const Real tol=1.e-8)
Bundle_AS(const unsigned maxSize=10, const Real coeff=0.0, const Real omega=2.0, const unsigned remSize=2)
unsigned solveEQPsubproblem(std::vector< Real > &s, Real &mu, const std::vector< Real > &g, const Real tol) const
void project(std::vector< Real > &x, const std::vector< Real > &v) const
void applyG(std::vector< Real > &Gx, const std::vector< Real > &x) const
void applyG_SymGS(std::vector< Real > &Gx, const std::vector< Real > &x) const
void computeLagMult(std::vector< Real > &lam, const Real mu, const std::vector< Real > &g) const
ROL::Ptr< Vector< Real > > ge_
unsigned solveDual(const Real t, const unsigned maxit=1000, const Real tol=1.e-8)
ROL::Ptr< Vector< Real > > eG_
std::set< unsigned > workingSet_
void applyPreconditioner(std::vector< Real > &Px, const std::vector< Real > &x) const
unsigned projectedCG(std::vector< Real > &x, Real &mu, const std::vector< Real > &b, const Real tol) const
Real dot(const std::vector< Real > &x, const std::vector< Real > &y) const
void initialize(const Vector< Real > &g)
void initializeDualSolver(void)
void computeResidualUpdate(std::vector< Real > &r, std::vector< Real > &g) const
bool isNonnegative(unsigned &ind, const std::vector< Real > &x) const
void applyFullMatrix(std::vector< Real > &Hx, const std::vector< Real > &x) const
Real computeStepSize(unsigned &ind, const std::vector< Real > &x, const std::vector< Real > &p) const
Real norm(const std::vector< Real > &x) const
void applyG_Jacobi(std::vector< Real > &Gx, const std::vector< Real > &x) const
ROL::Ptr< Vector< Real > > yG_
void applyPreconditioner_Identity(std::vector< Real > &Px, const std::vector< Real > &x) const
void applyPreconditioner_SymGS(std::vector< Real > &Px, const std::vector< Real > &x) const
ROL::Ptr< Vector< Real > > tG_
Provides the interface for and implements a bundle.
const Real dotGi(const unsigned i, const Vector< Real > &x) const
void setDualVariable(const unsigned i, const Real val)
virtual void initialize(const Vector< Real > &g)
unsigned solveDual_dim2(const Real t, const unsigned maxit=1000, const Real tol=1.e-8)
const Real GiGj(const unsigned i, const unsigned j) const
const Real alpha(const unsigned i) const
Real evaluateObjective(std::vector< Real > &g, const std::vector< Real > &x, const Real t) const
void addGi(const unsigned i, const Real a, Vector< Real > &x) const
unsigned size(void) const
unsigned solveDual_dim1(const Real t, const unsigned maxit=1000, const Real tol=1.e-8)
const Real getDualVariable(const unsigned i) const
Defines the linear algebra or vector space interface.
virtual ROL::Ptr< Vector > clone() const =0
Clone to make a new (uninitialized) vector.
constexpr auto dim