ROL
ROL_Bundle.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ************************************************************************
3 //
4 // Rapid Optimization Library (ROL) Package
5 // Copyright (2014) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact lead developers:
38 // Drew Kouri (dpkouri@sandia.gov) and
39 // Denis Ridzal (dridzal@sandia.gov)
40 //
41 // ************************************************************************
42 // @HEADER
43 
44 #ifndef ROL_BUNDLE_H
45 #define ROL_BUNDLE_H
46 
47 #include "ROL_Types.hpp"
48 #include "ROL_Vector.hpp"
49 
50 #include "Teuchos_RCP.hpp"
51 
52 #include <vector>
53 #include <set>
54 
59 namespace ROL {
60 
61 template<class Real>
62 class Bundle {
63 /***********************************************************************************************/
64 /***************** BUNDLE STORAGE **************************************************************/
65 /***********************************************************************************************/
66 private:
67  std::vector<Teuchos::RCP<Vector<Real> > > subgradients_;
68  std::vector<Real> linearizationErrors_;
69  std::vector<Real> distanceMeasures_;
70 
71  std::vector<Real> dualVariables_;
72 
73  Teuchos::RCP<Vector<Real> > tG_;
74  Teuchos::RCP<Vector<Real> > eG_;
75  Teuchos::RCP<Vector<Real> > yG_;
76 
77  unsigned size_;
78  unsigned maxSize_;
79  unsigned remSize_;
80 
81  Real coeff_;
82 
84 
85  void remove(const std::vector<unsigned> &ind) {
86  for (unsigned j = ind.back()+1; j < size_; j++) {
87  (subgradients_[j-1])->set(*(subgradients_[j]));
91  }
92  (subgradients_[size_-1])->zero();
95  dualVariables_[size_-1] = 0.0;
96  for (unsigned i = ind.size()-1; i > 0; --i) {
97  for (unsigned j = ind[i-1]+1; j < size_; j++) {
98  (subgradients_[j-1])->set(*(subgradients_[j]));
101  dualVariables_[j-1] = dualVariables_[j];
102  }
103  }
104  size_ -= ind.size();
105  }
106 
107  void add(const Vector<Real> &g, const Real le, const Real dm) {
108  (subgradients_[size_])->set(g);
110  distanceMeasures_[size_] = dm;
111  dualVariables_[size_] = 0.0;
112  size_++;
113  }
114 
115 /***********************************************************************************************/
116 /***************** BUNDLE MODIFICATION AND ACCESS ROUTINES *************************************/
117 /***********************************************************************************************/
118 public:
119  ~Bundle(void) {}
120  Bundle(const unsigned maxSize = 10, const Real coeff = 0.0, const unsigned remSize = 2)
121  : size_(0), maxSize_(maxSize), remSize_(remSize), coeff_(coeff), isInitialized_(false) {
122  remSize_ = ((remSize_ < 2) ? 2 : ((remSize_ > maxSize_-1) ? maxSize_-1 : remSize_));
123  subgradients_.clear();
124  subgradients_.assign(maxSize,Teuchos::null);
125  linearizationErrors_.clear();
127  distanceMeasures_.clear();
129  dualVariables_.clear();
130  dualVariables_.assign(maxSize_,0.0);
131  }
132 
133  void initialize(const Vector<Real> &g) {
134  if ( !isInitialized_ ) {
135  for (unsigned i = 0; i < maxSize_; i++) {
136  subgradients_[i] = g.clone();
137  }
138  (subgradients_[0])->set(g);
139  linearizationErrors_[0] = 0.0;
140  distanceMeasures_[0] = 0.0;
141  dualVariables_[0] = 1.0;
142  size_++;
143  isInitialized_ = true;
144  gx_ = g.clone();
145  ge_ = g.clone();
146  tG_ = g.clone();
147  yG_ = g.clone();
148  eG_ = g.clone();
149  }
150  }
151 
152  const Real linearizationError(const unsigned i) const {
153  return linearizationErrors_[i];
154  }
155 
156  const Real distanceMeasure(const unsigned i) const {
157  return distanceMeasures_[i];
158  }
159 
160  const Vector<Real> & subgradient(const unsigned i) const {
161  return *(subgradients_[i]);
162  }
163 
164  const Real computeAlpha(const Real dm, const Real le) const {
165  Real alpha = le;
166  if ( coeff_ > ROL_EPSILON ) {
167  alpha = std::max(coeff_*std::pow(dm,2.0),le);
168  }
169  return alpha;
170  }
171 
172  const Real alpha(const unsigned i) const {
174  }
175 
176  unsigned size(void) const {
177  return size_;
178  }
179 
180  void aggregate(Vector<Real> &aggSubGrad, Real &aggLinErr, Real &aggDistMeas) const {
181  aggSubGrad.zero(); aggLinErr = 0.0; aggDistMeas = 0.0; eG_->zero();
182  Real eLE = 0.0, eDM = 0.0, yLE = 0.0, yDM = 0.0, tLE = 0.0, tDM = 0.0;
183  for (unsigned i = 0; i < size_; i++) {
184  // Compute aggregate subgradient using Kahan's compensated sum
185  tG_->set(aggSubGrad);
186  yG_->set(*subgradients_[i]); yG_->scale(dualVariables_[i]); yG_->plus(*eG_);
187  aggSubGrad.set(*tG_); aggSubGrad.plus(*yG_);
188  eG_->set(*tG_); eG_->axpy(-1.0,aggSubGrad); eG_->plus(*yG_);
189  // Compute aggregate linearization error using Kahan's compensated sum
190  tLE = aggLinErr;
191  yLE = dualVariables_[i]*linearizationErrors_[i] + eLE;
192  aggLinErr = tLE + yLE;
193  eLE = (tLE - aggLinErr) + yLE;
194  // Compute aggregate distance measure using Kahan's compensated sum
195  tDM = aggDistMeas;
196  yDM = dualVariables_[i]*distanceMeasures_[i] + eDM;
197  aggDistMeas = tDM + yDM;
198  eDM = (tDM - aggDistMeas) + yDM;
199  }
200  }
201 
202  void reset(const Vector<Real> &g, const Real le, const Real dm) {
203  if (size_ == maxSize_) {
204  // Find indices to remove
205  unsigned loc = size_, cnt = 0;
206  std::vector<unsigned> ind(remSize_,0);
207  for (unsigned i = size_; i > 0; --i) {
208  if ( std::abs(linearizationErrors_[i-1]) < ROL_EPSILON ) {
209  loc = i-1;
210  break;
211  }
212  }
213  for (unsigned i = 0; i < size_; i++) {
214  if ( i < loc || i > loc ) {
215  ind[cnt] = i;
216  cnt++;
217  }
218  if (cnt == remSize_) {
219  break;
220  }
221  }
222  // Remove indices
223  remove(ind);
224  // Add aggregate subgradient
225  add(g,le,dm);
226  }
227  }
228 
229  void update(const bool flag, const Real linErr, const Real distMeas,
230  const Vector<Real> &g, const Vector<Real> &s) {
231  if ( flag ) {
232  // Serious step taken: Update linearlization errors and distance measures
233  for (unsigned i = 0; i < size_; i++) {
234  linearizationErrors_[i] += linErr - subgradients_[i]->dot(s);
235  distanceMeasures_[i] += distMeas;
236  }
238  distanceMeasures_[size_] = 0.0;
239  }
240  else {
241  // Null step taken:
242  linearizationErrors_[size_] = linErr;
243  distanceMeasures_[size_] = distMeas;
244  }
245  // Update (sub)gradient bundle
246  (subgradients_[size_])->set(g);
247  // Update dual variables
248  dualVariables_[size_] = 0.0;
249  // Update bundle size
250  size_++;
251  }
252 
253 /***********************************************************************************************/
254 /***************** DUAL CUTTING PLANE PROBLEM ROUTINES *****************************************/
255 /***********************************************************************************************/
256 private:
257  Teuchos::RCP<Vector<Real> > gx_;
258  Teuchos::RCP<Vector<Real> > ge_;
259  std::set<unsigned> workingSet_;
260  std::set<unsigned> nworkingSet_;
261 
262  void initializeDualSolver(void) {
263 // for (unsigned i = 0; i < maxSize_; i++) {
264 // dualVariables_[i] = 0.0;
265 // }
266 // dualVariables_[0] = 1.0;
267 // for (unsigned i = 0; i < maxSize_; i++) {
268 // dualVariables_[i] = ((i<size_) ? 1.0/(Real)size_ : 0.0);
269 // }
270 // nworkingSet_.clear();
271 // workingSet_.clear();
272 // for (unsigned i = 0; i < size_; i++) {
273 // nworkingSet_.insert(i);
274 // }
275  Real sum = 0.0, err = 0.0, tmp = 0.0, y = 0.0;
276  for (unsigned i = 0; i < size_; i++) {
277  // Compute sum of dualVariables_ using Kahan's compensated sum
278  tmp = sum;
279  y = dualVariables_[i] + err;
280  sum = tmp + y;
281  err = (tmp - sum) + y;
282  }
283  for (unsigned i = 0; i < size_; i++) {
284  dualVariables_[i] /= sum;
285  }
286  nworkingSet_.clear();
287  workingSet_.clear();
288  for (unsigned i = 0; i < size_; i++) {
289  if ( dualVariables_[i] == 0.0 ) {
290  workingSet_.insert(i);
291  }
292  else {
293  nworkingSet_.insert(i);
294  }
295  }
296  }
297 
298  Real evaluateObjective(std::vector<Real> &g, const std::vector<Real> &x, const Real t) const {
299  gx_->zero(); eG_->zero();
300  for (unsigned i = 0; i < size_; i++) {
301  // Compute Gx using Kahan's compensated sum
302  tG_->set(*gx_);
303  yG_->set(*eG_); yG_->axpy(x[i],*(subgradients_[i]));
304  gx_->set(*tG_); gx_->plus(*yG_);
305  eG_->set(*tG_); eG_->axpy(-1.0,*gx_); eG_->plus(*yG_);
306  }
307  Real Hx = 0.0, val = 0.0, err = 0.0, tmp = 0.0, y = 0.0;
308  for (unsigned i = 0; i < size_; i++) {
309  // Compute < g_i, Gx >
310  Hx = gx_->dot(*(subgradients_[i]));
311  // Add to the objective function value using Kahan's compensated sum
312  tmp = val;
313  y = x[i]*(0.5*Hx + alpha(i)/t) + err;
314  val = tmp + y;
315  err = (tmp - val) + y;
316  // Add gradient component
317  g[i] = Hx + alpha(i)/t;
318  }
319  return val;
320  }
321 
322  void applyFullMatrix(std::vector<Real> &Hx, const std::vector<Real> &x) const {
323  gx_->zero(); eG_->zero();
324  for (unsigned i = 0; i < size_; i++) {
325  // Compute Gx using Kahan's compensated sum
326  tG_->set(*gx_);
327  yG_->set(*eG_); yG_->axpy(x[i],*(subgradients_[i]));
328  gx_->set(*tG_); gx_->plus(*yG_);
329  eG_->set(*tG_); eG_->axpy(-1.0,*gx_); eG_->plus(*yG_);
330  }
331  for (unsigned i = 0; i < size_; i++) {
332  // Compute < g_i, Gx >
333  Hx[i] = subgradients_[i]->dot(*gx_);
334  }
335  }
336 
337  void applyMatrix(std::vector<Real> &Hx, const std::vector<Real> &x) const {
338  gx_->zero(); eG_->zero();
339  unsigned n = nworkingSet_.size();
340  typename std::set<unsigned>::iterator it = nworkingSet_.begin();
341  for (unsigned i = 0; i < n; i++) {
342  // Compute Gx using Kahan's compensated sum
343  tG_->set(*gx_);
344  yG_->set(*eG_); yG_->axpy(x[i],*(subgradients_[*it]));
345  gx_->set(*tG_); gx_->plus(*yG_);
346  eG_->set(*tG_); eG_->axpy(-1.0,*gx_); eG_->plus(*yG_);
347  it++;
348  }
349  it = nworkingSet_.begin();
350  for (unsigned i = 0; i < n; i++) {
351  // Compute < g_i, Gx >
352  Hx[i] = subgradients_[*it]->dot(*gx_); it++;
353  }
354  }
355 
356  void computeLagMult(std::vector<Real> &lam, const Real mu, const std::vector<Real> &g) const {
357  unsigned n = workingSet_.size();
358  if ( n > 0 ) {
359  lam.resize(n,0.0);
360  typename std::set<unsigned>::iterator it = workingSet_.begin();
361  for (unsigned i = 0; i < n; i++) {
362  lam[i] = g[*it] - mu; it++;
363  }
364  }
365  else {
366  lam.clear();
367  }
368  }
369 
370  bool isNonnegative(unsigned &ind, const std::vector<Real> &x) const {
371  bool flag = true;
372  unsigned n = workingSet_.size(); ind = size_;
373  if ( n > 0 ) {
374  Real min = ROL_OVERFLOW;
375  typename std::set<unsigned>::iterator it = workingSet_.begin();
376  for (unsigned i = 0; i < n; i++) {
377  if ( x[i] < min ) {
378  ind = *it;
379  min = x[i];
380  }
381  it++;
382  }
383  flag = ((min < -ROL_EPSILON) ? false : true);
384  }
385  return flag;
386  }
387 
388  Real computeAlpha(unsigned &ind, const std::vector<Real> &x, const std::vector<Real> &p) const {
389  Real alpha = 1.0, tmp = 0.0; ind = size_;
390  typename std::set<unsigned>::iterator it;
391  for (it = nworkingSet_.begin(); it != nworkingSet_.end(); it++) {
392  if ( p[*it] < -ROL_EPSILON ) {
393  tmp = -x[*it]/p[*it];
394  if ( alpha >= tmp ) {
395  alpha = tmp;
396  ind = *it;
397  }
398  }
399  }
400  return std::max(0.0,alpha);
401  }
402 
403  unsigned solveEQPsubproblem(std::vector<Real> &s, Real &mu,
404  const std::vector<Real> &g, const Real tol) const {
405  // Build reduced QP information
406  unsigned n = nworkingSet_.size(), cnt = 0;
407  mu = 0.0;
408  s.assign(size_,0.0);
409  if ( n > 0 ) {
410  std::vector<Real> gk(n,0.0);
411  typename std::set<unsigned>::iterator it = nworkingSet_.begin();
412  for (unsigned i = 0; i < n; i++) {
413  gk[i] = g[*it]; it++;
414  }
415  std::vector<Real> sk(n,0.0);
416  cnt = projectedCG(sk,mu,gk,tol);
417  it = nworkingSet_.begin();
418  for (unsigned i = 0; i < n; i++) {
419  s[*it] = sk[i]; it++;
420  }
421  }
422  return cnt;
423  }
424 
425  void applyPreconditioner(std::vector<Real> &Px, const std::vector<Real> &x) const {
426  int type = 0;
427  std::vector<Real> tmp(Px.size(),0.0);
428  switch (type) {
429  case 0: applyPreconditioner_Identity(tmp,x); break;
430  case 1: applyPreconditioner_Jacobi(tmp,x); break;
431  case 2: applyPreconditioner_SymGS(tmp,x); break;
432  }
434  }
435 
436  void applyG(std::vector<Real> &Gx, const std::vector<Real> &x) const {
437  int type = 0;
438  switch (type) {
439  case 0: applyG_Identity(Gx,x); break;
440  case 1: applyG_Jacobi(Gx,x); break;
441  case 2: applyG_SymGS(Gx,x); break;
442  }
443  }
444 
445  void applyPreconditioner_Identity(std::vector<Real> &Px, const std::vector<Real> &x) const {
446  unsigned dim = nworkingSet_.size();
447  Real sum = 0.0, err = 0.0, tmp = 0.0, y = 0.0;
448  for (unsigned i = 0; i < dim; i++) {
449  // Compute sum of x using Kahan's compensated sum
450  tmp = sum;
451  y = x[i] + err;
452  sum = tmp + y;
453  err = (tmp - sum) + y;
454  }
455  sum /= (Real)dim;
456  for (unsigned i = 0; i < dim; i++) {
457  Px[i] = x[i] - sum;
458  }
459  }
460 
461  void applyG_Identity(std::vector<Real> &Gx, const std::vector<Real> &x) const {
462  Gx.assign(x.begin(),x.end());
463  }
464 
465  void applyPreconditioner_Jacobi(std::vector<Real> &Px, const std::vector<Real> &x) const {
466  unsigned dim = nworkingSet_.size();
467  Real eHe = 0.0, sum = 0.0;
468  Real errX = 0.0, tmpX = 0.0, yX = 0.0, errE = 0.0, tmpE = 0.0, yE = 0.0;
469  std::vector<Real> gg(dim,0.0);
470  typename std::set<unsigned>::iterator it = nworkingSet_.begin();
471  for (unsigned i = 0; i < dim; i++) {
472  gg[i] = 1.0/std::abs(subgradients_[*it]->dot(*(subgradients_[*it]))); it++;
473  // Compute sum of inv(D)x using Kahan's aggregated sum
474  tmpX = sum;
475  yX = x[i]*gg[i] + errX;
476  sum = tmpX + errX;
477  errX = (tmpX - sum) + yX;
478  // Compute sum of inv(D)e using Kahan's aggregated sum
479  tmpE = eHe;
480  yE = gg[i] + errE;
481  eHe = tmpE + yE;
482  errE = (tmpE - eHe) + yE;
483  }
484  sum /= eHe;
485  for (unsigned i = 0; i < dim; i++) {
486  Px[i] = (x[i]-sum)*gg[i];
487  }
488  }
489 
490  void applyG_Jacobi(std::vector<Real> &Gx, const std::vector<Real> &x) const {
491  unsigned dim = nworkingSet_.size();
492  typename std::set<unsigned>::iterator it = nworkingSet_.begin();
493  for (unsigned i = 0; i < dim; i++) {
494  Gx[i] = std::abs(subgradients_[*it]->dot(*(subgradients_[*it])))*x[i]; it++;
495  }
496  }
497 
498  void applyPreconditioner_SymGS(std::vector<Real> &Px, const std::vector<Real> &x) const {
499  int dim = nworkingSet_.size();
500  //unsigned cnt = 0;
501  gx_->zero(); ge_->zero();
502  Real eHx = 0.0, eHe = 0.0;
503  // Forward substitution
504  std::vector<Real> x1(dim,0.0), e1(dim,0.0),gg(dim,0.0);
505  typename std::set<unsigned>::iterator it, jt;
506  it = nworkingSet_.begin();
507  for (int i = 0; i < dim; i++) {
508  gx_->zero(); ge_->zero(); jt = nworkingSet_.begin();
509  for (int j = 0; j < i; j++) {
510  gx_->axpy(x1[j],*(subgradients_[*jt]));
511  ge_->axpy(e1[j],*(subgradients_[*jt]));
512  jt++;
513  }
514  gg[i] = subgradients_[*it]->dot(*(subgradients_[*it]));
515  x1[i] = (x[i] - gx_->dot(*(subgradients_[*it])))/gg[i];
516  e1[i] = (1.0 - ge_->dot(*(subgradients_[*it])))/gg[i];
517  it++;
518  }
519  // Apply diagonal
520  for (int i = 0; i < dim; i++) {
521  x1[i] *= gg[i];
522  e1[i] *= gg[i];
523  }
524  // Back substitution
525  std::vector<Real> Hx(dim,0.0), He(dim,0.0); it = nworkingSet_.end();
526  for (int i = dim-1; i >= 0; --i) {
527  it--;
528  gx_->zero(); ge_->zero(); jt = nworkingSet_.end();
529  for (int j = dim-1; j >= i+1; --j) {
530  jt--;
531  gx_->axpy(Hx[j],*(subgradients_[*jt]));
532  ge_->axpy(He[j],*(subgradients_[*jt]));
533  }
534  Hx[i] = (x1[i] - gx_->dot(*(subgradients_[*it])))/gg[i];
535  He[i] = (e1[i] - ge_->dot(*(subgradients_[*it])))/gg[i];
536  // Compute sums
537  eHx += Hx[i];
538  eHe += He[i];
539  }
540  // Accumulate preconditioned vector
541  for (int i = 0; i < dim; i++) {
542  Px[i] = Hx[i] - (eHx/eHe)*He[i];
543  }
544  }
545 
546  void applyG_SymGS(std::vector<Real> &Gx, const std::vector<Real> &x) const {
547  unsigned dim = nworkingSet_.size();
548  typename std::set<unsigned>::iterator it = nworkingSet_.begin();
549  for (unsigned i = 0; i < dim; i++) {
550  Gx[i] = std::abs(subgradients_[*it]->dot(*(subgradients_[*it])))*x[i]; it++;
551  }
552  }
553 
554  void computeResidualUpdate(std::vector<Real> &r, std::vector<Real> &g) const {
555  unsigned n = g.size();
556  std::vector<Real> Gg(n,0.0);
557  Real y = 0.0, ytmp = 0.0, yprt = 0.0, yerr = 0.0;
558  applyPreconditioner(g,r);
559  applyG(Gg,g);
560  // Compute multiplier using Kahan's compensated sum
561  for (unsigned i = 0; i < n; i++) {
562  ytmp = y;
563  yprt = (r[i] - Gg[i]) + yerr;
564  y = ytmp + yprt;
565  yerr = (ytmp - y) + yprt;
566  }
567  y /= (Real)n;
568  for (unsigned i = 0; i < n; i++) {
569  r[i] -= y;
570  }
571  applyPreconditioner(g,r);
572  }
573 
574  unsigned projectedCG(std::vector<Real> &x, Real &mu, const std::vector<Real> &b, const Real tol) const {
575  unsigned n = nworkingSet_.size();
576  std::vector<Real> r(n,0.0), r0(n,0.0), g(n,0.0), d(n,0.0), Ad(n,0.0);
577  // Compute residual Hx + g = g with x = 0
578  x.assign(n,0.0);
579  scale(r,1.0,b);
580  r0.assign(r.begin(),r.end());
581  // Precondition residual
583  Real rg = dot(r,g), rg0 = 0.0;
584  // Get search direction
585  scale(d,-1.0,g);
586  Real alpha = 0.0, kappa = 0.0, beta = 0.0;
587  Real CGtol = std::min(tol,1.e-2*rg);
588  unsigned cnt = 0;
589  while (rg > CGtol && cnt < 2*n+1) {
590  applyMatrix(Ad,d);
591  kappa = dot(d,Ad);
592  alpha = rg/kappa;
593  axpy(alpha,d,x);
594  axpy(alpha,Ad,r);
595  axpy(alpha,Ad,r0);
597  rg0 = rg;
598  rg = dot(r,g);
599  beta = rg/rg0;
600  scale(d,beta);
601  axpy(-1.0,g,d);
602  cnt++;
603  }
604  // Compute multiplier for equality constraint using Kahan's compensated sum
605  mu = 0.0;
606  Real err = 0.0, tmp = 0.0, y = 0.0;
607  for (unsigned i = 0; i < n; i++) {
608  tmp = mu;
609  y = r0[i] + err;
610  mu = tmp + y;
611  err = (tmp - mu) + y;
612  }
613  mu /= (Real)n;
614  // Return iteration count
615  return cnt;
616  }
617 
618  Real dot(const std::vector<Real> &x, const std::vector<Real> &y) const {
619  // Compute dot product of two vectors using Kahan's compensated sum
620  Real val = 0.0, err = 0.0, tmp = 0.0, y0 = 0.0;
621  unsigned n = std::min(x.size(),y.size());
622  for (unsigned i = 0; i < n; i++) {
623  tmp = val;
624  y0 = x[i]*y[i] + err;
625  val = tmp + y0;
626  err = (tmp - val) + y0;
627  }
628  return val;
629  }
630 
631  Real norm(const std::vector<Real> &x) const {
632  return std::sqrt(dot(x,x));
633  }
634 
635  void axpy(const Real a, const std::vector<Real> &x, std::vector<Real> &y) const {
636  unsigned n = std::min(y.size(),x.size());
637  for (unsigned i = 0; i < n; i++) {
638  y[i] += a*x[i];
639  }
640  }
641 
642  void scale(std::vector<Real> &x, const Real a) const {
643  for (unsigned i = 0; i < x.size(); i++) {
644  x[i] *= a;
645  }
646  }
647 
648  void scale(std::vector<Real> &x, const Real a, const std::vector<Real> &y) const {
649  unsigned n = std::min(x.size(),y.size());
650  for (unsigned i = 0; i < n; i++) {
651  x[i] = a*y[i];
652  }
653  }
654 
655  unsigned solveDual_dim1(const Real t, const unsigned maxit = 1000, const Real tol = 1.e-8) {
656  dualVariables_[0] = 1.0;
657  //std::cout << "dim = " << size_ << " iter = " << 0 << " CONVERGED!\n";
658  return 0;
659  }
660 
661  unsigned solveDual_dim2(const Real t, const unsigned maxit = 1000, const Real tol = 1.e-8) {
662  gx_->set(*subgradients_[0]); gx_->axpy(-1.0,*subgradients_[1]);
663  Real diffg = gx_->dot(*gx_);
664  if ( std::abs(diffg) > ROL_EPSILON ) {
665  Real diffa = (alpha(0)-alpha(1))/t;
666  Real gdiffg = subgradients_[1]->dot(*gx_);
667  dualVariables_[0] = std::min(1.0,std::max(0.0,-(gdiffg+diffa)/diffg));
668  dualVariables_[1] = 1.0-dualVariables_[0];
669  }
670  else {
671  if ( std::abs(alpha(0)-alpha(1)) > ROL_EPSILON ) {
672  if ( alpha(0) < alpha(1) ) {
673  dualVariables_[0] = 1.0; dualVariables_[1] = 0.0;
674  }
675  else if ( alpha(0) > alpha(1) ) {
676  dualVariables_[0] = 0.0; dualVariables_[1] = 1.0;
677  }
678  }
679  else {
680  dualVariables_[0] = 0.5; dualVariables_[1] = 0.5;
681  }
682  }
683  //std::cout << "dim = " << size_ << " iter = " << 0 << " CONVERGED!\n";
684  return 0;
685  }
686 
687  unsigned solveDual_arbitrary(const Real t, const unsigned maxit = 1000, const Real tol = 1.e-8) {
689  bool nonneg = false;
690  unsigned ind = 0, i = 0, CGiter = 0;
691  Real snorm = 0.0, alpha = 0.0, mu = 0.0;
692  std::vector<Real> s(size_,0.0), Hs(size_,0.0), g(size_,0.0), lam(size_+1,0.0);
693  //Real val = evaluateObjective(g,dualVariables_,t);
695  for (i = 0; i < maxit; i++) {
696  CGiter += solveEQPsubproblem(s,mu,g,tol);
697  snorm = norm(s);
698  if ( snorm < ROL_EPSILON ) {
699  computeLagMult(lam,mu,g);
700  nonneg = isNonnegative(ind,lam);
701  if ( nonneg ) {
702  break;
703  }
704  else {
705  alpha = 1.0;
706  if ( ind < size_ ) {
707  workingSet_.erase(ind);
708  nworkingSet_.insert(ind);
709  }
710  }
711  }
712  else {
714  if ( alpha > 0.0 ) {
716  applyFullMatrix(Hs,s);
717  axpy(alpha,Hs,g);
718  }
719  if (ind < size_) {
720  workingSet_.insert(ind);
721  nworkingSet_.erase(ind);
722  }
723  }
724  //std::cout << "iter = " << i << " snorm = " << snorm << " alpha = " << alpha << "\n";
725  }
726  //Real crit = computeCriticality(g);
727  //std::cout << "Criticality Measure: " << crit << "\n";
728  //std::cout << "dim = " << size_ << " iter = " << i << " CGiter = " << CGiter << " CONVERGED!\n";
729  return i;
730  }
731 
732 public:
733  unsigned solveDual(const Real t, const unsigned maxit = 1000, const Real tol = 1.e-8) {
734  unsigned iter = 0;
735  if (size_ == 1) {
736  iter = solveDual_dim1(t,maxit,tol);
737  }
738  else if (size_ == 2) {
739  iter = solveDual_dim2(t,maxit,tol);
740  }
741  else {
742  iter = solveDual_arbitrary(t,maxit,tol);
743  }
744  return iter;
745  }
746 
747 private:
748  /************************************************************************/
749  /********************** PROJECTION ONTO FEASIBLE SET ********************/
750  /************************************************************************/
751  void project(std::vector<Real> &x, const std::vector<Real> &v) const {
752  std::vector<Real> vsort(size_,0.0);
753  vsort.assign(v.begin(),v.end());
754  std::sort(vsort.begin(),vsort.end());
755  Real sum = -1.0, lam = 0.0;
756  for (int i = size_-1; i > 0; i--) {
757  sum += vsort[i];
758  if ( sum >= ((Real)(size_-i))*vsort[i-1] ) {
759  lam = sum/(Real)(size_-i);
760  break;
761  }
762  }
763  if (lam == 0.0) {
764  lam = (sum+vsort[0])/(Real)size_;
765  }
766  for (int i = 0; i < size_; i++) {
767  x[i] = std::max(0.0,v[i] - lam);
768  }
769  }
770 
771  Real computeCriticality(const std::vector<Real> &g) {
772  std::vector<Real> x(size_,0.0), Px(size_,0.0);
773  axpy(1.0,dualVariables_,x);
774  axpy(-1.0,g,x);
775  project(Px,x);
776  scale(x,0.0);
777  axpy(1.0,dualVariables_,x);
778  axpy(-1.0,Px,x);
779  return norm(x);
780  }
781 }; // class Bundle
782 
783 } // namespace ROL
784 
785 #endif
786 
787 // void aggregate(Vector<Real> &aggSubGrad, Real &aggLinErr, Real &aggDistMeas) const {
788 // aggSubGrad.zero(); aggLinErr = 0.0; aggDistMeas = 0.0;
789 // for (unsigned i = 0; i < size_; i++) {
790 // //if ( dualVariables_[i] > ROL_EPSILON ) {
791 // aggSubGrad.axpy(dualVariables_[i],*(subgradients_[i]));
792 // aggLinErr += dualVariables_[i]*linearizationErrors_[i];
793 // aggDistMeas += dualVariables_[i]*distanceMeasures_[i];
794 // //}
795 // }
796 // }
unsigned maxSize_
Definition: ROL_Bundle.hpp:78
void initializeDualSolver(void)
Definition: ROL_Bundle.hpp:262
void applyPreconditioner_Jacobi(std::vector< Real > &Px, const std::vector< Real > &x) const
Definition: ROL_Bundle.hpp:465
void scale(std::vector< Real > &x, const Real a) const
Definition: ROL_Bundle.hpp:642
std::set< unsigned > workingSet_
Definition: ROL_Bundle.hpp:259
virtual void plus(const Vector &x)=0
Compute , where .
void update(const bool flag, const Real linErr, const Real distMeas, const Vector< Real > &g, const Vector< Real > &s)
Definition: ROL_Bundle.hpp:229
Real norm(const std::vector< Real > &x) const
Definition: ROL_Bundle.hpp:631
unsigned size_
Definition: ROL_Bundle.hpp:77
Teuchos::RCP< Vector< Real > > yG_
Definition: ROL_Bundle.hpp:75
const Real linearizationError(const unsigned i) const
Definition: ROL_Bundle.hpp:152
void applyFullMatrix(std::vector< Real > &Hx, const std::vector< Real > &x) const
Definition: ROL_Bundle.hpp:322
void applyMatrix(std::vector< Real > &Hx, const std::vector< Real > &x) const
Definition: ROL_Bundle.hpp:337
Contains definitions of custom data types in ROL.
unsigned solveEQPsubproblem(std::vector< Real > &s, Real &mu, const std::vector< Real > &g, const Real tol) const
Definition: ROL_Bundle.hpp:403
Real computeCriticality(const std::vector< Real > &g)
Definition: ROL_Bundle.hpp:771
virtual Teuchos::RCP< Vector > clone() const =0
Clone to make a new (uninitialized) vector.
void reset(const Vector< Real > &g, const Real le, const Real dm)
Definition: ROL_Bundle.hpp:202
virtual void zero()
Set to zero vector.
Definition: ROL_Vector.hpp:155
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:72
unsigned solveDual(const Real t, const unsigned maxit=1000, const Real tol=1.e-8)
Definition: ROL_Bundle.hpp:733
const Vector< Real > & subgradient(const unsigned i) const
Definition: ROL_Bundle.hpp:160
void applyPreconditioner(std::vector< Real > &Px, const std::vector< Real > &x) const
Definition: ROL_Bundle.hpp:425
std::set< unsigned > nworkingSet_
Definition: ROL_Bundle.hpp:260
const Real computeAlpha(const Real dm, const Real le) const
Definition: ROL_Bundle.hpp:164
std::vector< Real > dualVariables_
Definition: ROL_Bundle.hpp:71
void scale(std::vector< Real > &x, const Real a, const std::vector< Real > &y) const
Definition: ROL_Bundle.hpp:648
void applyG_SymGS(std::vector< Real > &Gx, const std::vector< Real > &x) const
Definition: ROL_Bundle.hpp:546
Teuchos::RCP< Vector< Real > > ge_
Definition: ROL_Bundle.hpp:258
Real dot(const std::vector< Real > &x, const std::vector< Real > &y) const
Definition: ROL_Bundle.hpp:618
void computeLagMult(std::vector< Real > &lam, const Real mu, const std::vector< Real > &g) const
Definition: ROL_Bundle.hpp:356
const Real alpha(const unsigned i) const
Definition: ROL_Bundle.hpp:172
std::vector< Teuchos::RCP< Vector< Real > > > subgradients_
Definition: ROL_Bundle.hpp:67
unsigned projectedCG(std::vector< Real > &x, Real &mu, const std::vector< Real > &b, const Real tol) const
Definition: ROL_Bundle.hpp:574
unsigned remSize_
Definition: ROL_Bundle.hpp:79
void applyG_Identity(std::vector< Real > &Gx, const std::vector< Real > &x) const
Definition: ROL_Bundle.hpp:461
Real computeAlpha(unsigned &ind, const std::vector< Real > &x, const std::vector< Real > &p) const
Definition: ROL_Bundle.hpp:388
void applyG_Jacobi(std::vector< Real > &Gx, const std::vector< Real > &x) const
Definition: ROL_Bundle.hpp:490
std::vector< Real > distanceMeasures_
Definition: ROL_Bundle.hpp:69
Real evaluateObjective(std::vector< Real > &g, const std::vector< Real > &x, const Real t) const
Definition: ROL_Bundle.hpp:298
bool isNonnegative(unsigned &ind, const std::vector< Real > &x) const
Definition: ROL_Bundle.hpp:370
void applyPreconditioner_SymGS(std::vector< Real > &Px, const std::vector< Real > &x) const
Definition: ROL_Bundle.hpp:498
void aggregate(Vector< Real > &aggSubGrad, Real &aggLinErr, Real &aggDistMeas) const
Definition: ROL_Bundle.hpp:180
unsigned solveDual_dim1(const Real t, const unsigned maxit=1000, const Real tol=1.e-8)
Definition: ROL_Bundle.hpp:655
void applyPreconditioner_Identity(std::vector< Real > &Px, const std::vector< Real > &x) const
Definition: ROL_Bundle.hpp:445
Teuchos::RCP< Vector< Real > > eG_
Definition: ROL_Bundle.hpp:74
unsigned size(void) const
Definition: ROL_Bundle.hpp:176
void applyG(std::vector< Real > &Gx, const std::vector< Real > &x) const
Definition: ROL_Bundle.hpp:436
const Real distanceMeasure(const unsigned i) const
Definition: ROL_Bundle.hpp:156
Teuchos::RCP< Vector< Real > > tG_
Definition: ROL_Bundle.hpp:73
virtual void set(const Vector &x)
Set where .
Definition: ROL_Vector.hpp:194
void project(std::vector< Real > &x, const std::vector< Real > &v) const
Definition: ROL_Bundle.hpp:751
static const double ROL_OVERFLOW
Platform-dependent maximum double.
Definition: ROL_Types.hpp:123
void axpy(const Real a, const std::vector< Real > &x, std::vector< Real > &y) const
Definition: ROL_Bundle.hpp:635
std::vector< Real > linearizationErrors_
Definition: ROL_Bundle.hpp:68
unsigned solveDual_dim2(const Real t, const unsigned maxit=1000, const Real tol=1.e-8)
Definition: ROL_Bundle.hpp:661
void initialize(const Vector< Real > &g)
Definition: ROL_Bundle.hpp:133
void add(const Vector< Real > &g, const Real le, const Real dm)
Definition: ROL_Bundle.hpp:107
Teuchos::RCP< Vector< Real > > gx_
Definition: ROL_Bundle.hpp:257
bool isInitialized_
Definition: ROL_Bundle.hpp:83
Bundle(const unsigned maxSize=10, const Real coeff=0.0, const unsigned remSize=2)
Definition: ROL_Bundle.hpp:120
void computeResidualUpdate(std::vector< Real > &r, std::vector< Real > &g) const
Definition: ROL_Bundle.hpp:554
Provides the interface for and implments a bundle.
Definition: ROL_Bundle.hpp:62
static const double ROL_EPSILON
Platform-dependent machine epsilon.
Definition: ROL_Types.hpp:115
unsigned solveDual_arbitrary(const Real t, const unsigned maxit=1000, const Real tol=1.e-8)
Definition: ROL_Bundle.hpp:687