gtsam 4.1.1
gtsam
AcceleratedPowerMethod.h
Go to the documentation of this file.
1/* ----------------------------------------------------------------------------
2
3 * GTSAM Copyright 2010-2019, Georgia Tech Research Corporation,
4 * Atlanta, Georgia 30332-0415
5 * All Rights Reserved
6 * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7
8 * See LICENSE for the license information
9
10 * -------------------------------------------------------------------------- */
11
20#pragma once
21
23
24namespace gtsam {
25
26using Sparse = Eigen::SparseMatrix<double>;
27
50template <class Operator>
51class AcceleratedPowerMethod : public PowerMethod<Operator> {
52
53 double beta_ = 0; // a Polyak momentum term
54
55 Vector previousVector_; // store previous vector
56
57 public:
63 const Operator &A, const boost::optional<Vector> initial = boost::none,
64 double initialBeta = 0.0)
65 : PowerMethod<Operator>(A, initial) {
66 // initialize Ritz eigen vector and previous vector
67 this->ritzVector_ = initial ? initial.get() : Vector::Random(this->dim_);
68 this->ritzVector_.normalize();
69 previousVector_ = Vector::Zero(this->dim_);
70
71 // initialize beta_
72 beta_ = initialBeta;
73 }
74
80 Vector acceleratedPowerIteration (const Vector &x1, const Vector &x0,
81 const double beta) const {
82 Vector y = this->A_ * x1 - beta * x0;
83 y.normalize();
84 return y;
85 }
86
92 Vector acceleratedPowerIteration () const {
93 Vector y = acceleratedPowerIteration(this->ritzVector_, previousVector_, beta_);
94 return y;
95 }
96
101 double estimateBeta(const size_t T = 10) const {
102 // set initial estimation of maxBeta
103 Vector initVector = this->ritzVector_;
104 const double up = initVector.dot( this->A_ * initVector );
105 const double down = initVector.dot(initVector);
106 const double mu = up / down;
107 double maxBeta = mu * mu / 4;
108 size_t maxIndex;
109 std::vector<double> betas;
110
111 Matrix R = Matrix::Zero(this->dim_, 10);
112 // run T times of iteration to find the beta that has the largest Rayleigh quotient
113 for (size_t t = 0; t < T; t++) {
114 // after each t iteration, reset the betas with the current maxBeta
115 betas = {2 / 3 * maxBeta, 0.99 * maxBeta, maxBeta, 1.01 * maxBeta,
116 1.5 * maxBeta};
117 // iterate through every beta value
118 for (size_t k = 0; k < betas.size(); ++k) {
119 // initialize x0 and x00 in each iteration of each beta
120 Vector x0 = initVector;
121 Vector x00 = Vector::Zero(this->dim_);
122 // run 10 steps of accelerated power iteration with this beta
123 for (size_t j = 1; j < 10; j++) {
124 if (j < 2) {
125 R.col(0) = acceleratedPowerIteration(x0, x00, betas[k]);
126 R.col(1) = acceleratedPowerIteration(R.col(0), x0, betas[k]);
127 } else {
128 R.col(j) = acceleratedPowerIteration(R.col(j - 1), R.col(j - 2),
129 betas[k]);
130 }
131 }
132 // compute the Rayleigh quotient for the randomly sampled vector after
133 // 10 steps of power accelerated iteration
134 const Vector x = R.col(9);
135 const double up = x.dot(this->A_ * x);
136 const double down = x.dot(x);
137 const double mu = up / down;
138 // store the momentum with largest Rayleigh quotient and its according index of beta_
139 if (mu * mu / 4 > maxBeta) {
140 // save the max beta index
141 maxIndex = k;
142 maxBeta = mu * mu / 4;
143 }
144 }
145 }
146 // set beta_ to momentum with largest Rayleigh quotient
147 return betas[maxIndex];
148 }
149
156 bool compute(size_t maxIterations, double tol) {
157 // Starting
158 bool isConverged = false;
159
160 for (size_t i = 0; i < maxIterations && !isConverged; i++) {
161 ++(this->nrIterations_);
162 Vector tmp = this->ritzVector_;
163 // update the ritzVector after accelerated power iteration
164 this->ritzVector_ = acceleratedPowerIteration();
165 // update the previousVector with ritzVector
166 previousVector_ = tmp;
167 // update the ritzValue
168 this->ritzValue_ = this->ritzVector_.dot(this->A_ * this->ritzVector_);
169 isConverged = this->converged(tol);
170 }
171
172 return isConverged;
173 }
174};
175
176} // namespace gtsam
Power method for fast eigenvalue and eigenvector computation.
Global functions in a separate testing namespace.
Definition: chartTesting.h:28
Compute maximum Eigenpair with accelerated power method.
Definition: AcceleratedPowerMethod.h:51
Vector acceleratedPowerIteration(const Vector &x1, const Vector &x0, const double beta) const
Run accelerated power iteration to get ritzVector with beta and previous two ritzVector x0 and x00,...
Definition: AcceleratedPowerMethod.h:80
AcceleratedPowerMethod(const Operator &A, const boost::optional< Vector > initial=boost::none, double initialBeta=0.0)
Constructor from aim matrix A (given as Matrix or Sparse), optional intial vector as ritzVector.
Definition: AcceleratedPowerMethod.h:62
double estimateBeta(const size_t T=10) const
Tuning the momentum beta using the Best Heavy Ball algorithm in Ref(3), T is the iteration time to fi...
Definition: AcceleratedPowerMethod.h:101
Vector acceleratedPowerIteration() const
Run accelerated power iteration to get ritzVector with beta and previous two ritzVector x0 and x00,...
Definition: AcceleratedPowerMethod.h:92
bool compute(size_t maxIterations, double tol)
Start the accelerated iteration, after performing the accelerated iteration, calculate the ritz error...
Definition: AcceleratedPowerMethod.h:156
Compute maximum Eigenpair with power method.
Definition: PowerMethod.h:57
const Operator & A_
Const reference to an externally-held matrix whose minimum-eigenvalue we want to compute.
Definition: PowerMethod.h:63
bool converged(double tol) const
After Perform power iteration on a single Ritz value, check if the Ritz residual for the current Ritz...
Definition: PowerMethod.h:112