ViennaCL - The Vienna Computing Library  1.6.2
Free open-source GPU-accelerated linear algebra and solver library.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
lanczos.hpp
Go to the documentation of this file.
1 #ifndef VIENNACL_LINALG_LANCZOS_HPP_
2 #define VIENNACL_LINALG_LANCZOS_HPP_
3 
4 /* =========================================================================
5  Copyright (c) 2010-2014, Institute for Microelectronics,
6  Institute for Analysis and Scientific Computing,
7  TU Wien.
8  Portions of this software are copyright by UChicago Argonne, LLC.
9 
10  -----------------
11  ViennaCL - The Vienna Computing Library
12  -----------------
13 
14  Project Head: Karl Rupp rupp@iue.tuwien.ac.at
15 
16  (A list of authors and contributors can be found in the PDF manual)
17 
18  License: MIT (X11), see file LICENSE in the base directory
19 ============================================================================= */
20 
27 #include <cmath>
28 #include <vector>
29 #include "viennacl/vector.hpp"
31 #include "viennacl/linalg/prod.hpp"
36 #include <boost/random.hpp>
37 #include <boost/random/mersenne_twister.hpp>
38 #include <boost/numeric/ublas/matrix.hpp>
39 #include <boost/numeric/ublas/matrix_proxy.hpp>
40 #include <boost/numeric/ublas/matrix_expression.hpp>
41 #include <boost/numeric/ublas/matrix_sparse.hpp>
42 #include <boost/numeric/ublas/vector.hpp>
43 #include <boost/numeric/ublas/operation.hpp>
44 #include <boost/numeric/ublas/vector_expression.hpp>
45 #include <boost/numeric/ublas/io.hpp>
46 
47 namespace viennacl
48 {
49 namespace linalg
50 {
51 
55 {
56 public:
57 
58  enum
59  {
63  };
64 
73  lanczos_tag(double factor = 0.75,
74  vcl_size_t numeig = 10,
75  int met = 0,
76  vcl_size_t krylov = 100) : factor_(factor), num_eigenvalues_(numeig), method_(met), krylov_size_(krylov) {}
77 
79  void num_eigenvalues(vcl_size_t numeig){ num_eigenvalues_ = numeig; }
80 
82  vcl_size_t num_eigenvalues() const { return num_eigenvalues_; }
83 
85  void factor(double fct) { factor_ = fct; }
86 
88  double factor() const { return factor_; }
89 
91  void krylov_size(vcl_size_t max) { krylov_size_ = max; }
92 
94  vcl_size_t krylov_size() const { return krylov_size_; }
95 
97  void method(int met){ method_ = met; }
98 
100  int method() const { return method_; }
101 
102 
103 private:
104  double factor_;
105  vcl_size_t num_eigenvalues_;
106  int method_; // see enum defined above for possible values
107  vcl_size_t krylov_size_;
108 };
109 
110 
111 namespace detail
112 {
123  template< typename MatrixT, typename VectorT >
124  std::vector<
126  >
127  lanczosPRO (MatrixT const& A, VectorT & r, vcl_size_t size, lanczos_tag const & tag)
128  {
130  typedef typename viennacl::result_of::cpu_value_type<ScalarType>::type CPU_ScalarType;
131 
132 
133  // generation of some random numbers, used for lanczos PRO algorithm
134  boost::mt11213b mt;
135  boost::normal_distribution<CPU_ScalarType> N(0, 1);
136  boost::bernoulli_distribution<CPU_ScalarType> B(0.5);
137  boost::triangle_distribution<CPU_ScalarType> T(-1, 0, 1);
138 
139  boost::variate_generator<boost::mt11213b&, boost::normal_distribution<CPU_ScalarType> > get_N(mt, N);
140  boost::variate_generator<boost::mt11213b&, boost::bernoulli_distribution<CPU_ScalarType> > get_B(mt, B);
141  boost::variate_generator<boost::mt11213b&, boost::triangle_distribution<CPU_ScalarType> > get_T(mt, T);
142 
143 
144  long i, k, retry, reorths;
145  std::vector<long> l_bound(size/2), u_bound(size/2);
146  bool second_step;
147  CPU_ScalarType squ_eps, eta, temp, eps, retry_th;
148  vcl_size_t n = r.size();
149  std::vector< std::vector<CPU_ScalarType> > w(2, std::vector<CPU_ScalarType>(size));
150  CPU_ScalarType cpu_beta;
151 
152  boost::numeric::ublas::vector<CPU_ScalarType> s(n);
153 
154  VectorT t(n);
155  CPU_ScalarType inner_rt;
156  ScalarType vcl_beta;
157  ScalarType vcl_alpha;
158  std::vector<CPU_ScalarType> alphas, betas;
159  boost::numeric::ublas::matrix<CPU_ScalarType> Q(n, size);
160 
161  second_step = false;
162  eps = std::numeric_limits<CPU_ScalarType>::epsilon();
163  squ_eps = std::sqrt(eps);
164  retry_th = 1e-2;
165  eta = std::exp(std::log(eps) * tag.factor());
166  reorths = 0;
167  retry = 0;
168 
169  vcl_beta = viennacl::linalg::norm_2(r);
170 
171  r /= vcl_beta;
172 
175 
176  VectorT u = viennacl::linalg::prod(A, r);
177  vcl_alpha = viennacl::linalg::inner_prod(u, r);
178  alphas.push_back(vcl_alpha);
179  w[0][0] = 1;
180  betas.push_back(vcl_beta);
181 
182  long batches = 0;
183  for (i = 1;i < static_cast<long>(size); i++)
184  {
185  r = u - vcl_alpha * r;
186  vcl_beta = viennacl::linalg::norm_2(r);
187 
188  betas.push_back(vcl_beta);
189  r = r / vcl_beta;
190 
191  vcl_size_t index = vcl_size_t(i % 2);
192  w[index][vcl_size_t(i)] = 1;
193  k = (i + 1) % 2;
194  w[index][0] = (betas[1] * w[vcl_size_t(k)][1] + (alphas[0] - vcl_alpha) * w[vcl_size_t(k)][0] - betas[vcl_size_t(i) - 1] * w[index][0]) / vcl_beta + eps * 0.3 * get_N() * (betas[1] + vcl_beta);
195 
196  for (vcl_size_t j = 1; j < vcl_size_t(i - 1); j++)
197  {
198  w[index][j] = (betas[j + 1] * w[vcl_size_t(k)][j + 1] + (alphas[j] - vcl_alpha) * w[vcl_size_t(k)][j] + betas[j] * w[vcl_size_t(k)][j - 1] - betas[vcl_size_t(i) - 1] * w[index][j]) / vcl_beta + eps * 0.3 * get_N() * (betas[j + 1] + vcl_beta);
199  }
200  w[index][vcl_size_t(i) - 1] = 0.6 * eps * CPU_ScalarType(n) * get_N() * betas[1] / vcl_beta;
201 
202  if (second_step)
203  {
204  for (vcl_size_t j = 0; j < vcl_size_t(batches); j++)
205  {
206  l_bound[vcl_size_t(j)]++;
207  u_bound[vcl_size_t(j)]--;
208 
209  for (k = l_bound[j];k < u_bound[j];k++)
210  {
212  inner_rt = viennacl::linalg::inner_prod(r,t);
213  r = r - inner_rt * t;
214  w[index][vcl_size_t(k)] = 1.5 * eps * get_N();
215  reorths++;
216  }
217  }
218  temp = viennacl::linalg::norm_2(r);
219  r = r / temp;
220  vcl_beta = vcl_beta * temp;
221  second_step = false;
222  }
223  batches = 0;
224 
225  for (vcl_size_t j = 0; j < vcl_size_t(i); j++)
226  {
227  if (std::fabs(w[index][j]) >= squ_eps)
228  {
230  inner_rt = viennacl::linalg::inner_prod(r,t);
231  r = r - inner_rt * t;
232  w[index][j] = 1.5 * eps * get_N();
233  k = long(j) - 1;
234  reorths++;
235  while (k >= 0 && std::fabs(w[index][vcl_size_t(k)]) > eta)
236  {
238  inner_rt = viennacl::linalg::inner_prod(r,t);
239  r = r - inner_rt * t;
240  w[index][vcl_size_t(k)] = 1.5 * eps * get_N();
241  k--;
242  reorths++;
243  }
244  l_bound[vcl_size_t(batches)] = k + 1;
245  k = long(j) + 1;
246 
247  while (k < i && std::fabs(w[index][vcl_size_t(k)]) > eta)
248  {
250  inner_rt = viennacl::linalg::inner_prod(r,t);
251  r = r - inner_rt * t;
252  w[index][vcl_size_t(k)] = 1.5 * eps * get_N();
253  k++;
254  reorths++;
255  }
256  u_bound[vcl_size_t(batches)] = k - 1;
257  batches++;
258  j = vcl_size_t(k);
259  }
260  }
261 
262  if (batches > 0)
263  {
264  temp = viennacl::linalg::norm_2(r);
265  r = r / temp;
266  vcl_beta = vcl_beta * temp;
267  second_step = true;
268 
269  while (temp < retry_th)
270  {
271  for (vcl_size_t j = 0; j < vcl_size_t(i); j++)
272  {
274  inner_rt = viennacl::linalg::inner_prod(r,t);
275  r = r - inner_rt * t;
276  reorths++;
277  }
278  retry++;
279  temp = viennacl::linalg::norm_2(r);
280  r = r / temp;
281  vcl_beta = vcl_beta * temp;
282  }
283  }
284 
287 
288  cpu_beta = vcl_beta;
289  s = - cpu_beta * boost::numeric::ublas::column(Q, vcl_size_t(i - 1));
291  u += viennacl::linalg::prod(A, r);
292  vcl_alpha = viennacl::linalg::inner_prod(u, r);
293  alphas.push_back(vcl_alpha);
294  }
295 
296  return bisect(alphas, betas);
297  }
298 
299 
308  template<typename MatrixT, typename VectorT>
309  std::vector<
311  >
312  lanczos (MatrixT const& A, VectorT & r, vcl_size_t size, lanczos_tag)
313  {
315  typedef typename viennacl::result_of::cpu_value_type<ScalarType>::type CPU_ScalarType;
316 
317  ScalarType vcl_beta;
318  ScalarType vcl_alpha;
319  std::vector<CPU_ScalarType> alphas, betas;
320  CPU_ScalarType norm;
321  vcl_size_t n = r.size();
322  VectorT u(n), t(n);
323  boost::numeric::ublas::vector<CPU_ScalarType> s(r.size()), u_zero(n), q(n);
324  boost::numeric::ublas::matrix<CPU_ScalarType> Q(n, size);
325 
326  u_zero = boost::numeric::ublas::zero_vector<CPU_ScalarType>(n);
327  detail::copy_vec_to_vec(u_zero, u);
328  norm = norm_2(r);
329 
330  for (vcl_size_t i = 0;i < size; i++)
331  {
332  r /= norm;
333  vcl_beta = norm;
334 
337 
338  u += prod(A, r);
339  vcl_alpha = inner_prod(u, r);
340  r = u - vcl_alpha * r;
341  norm = norm_2(r);
342 
345 
346  u = - norm * t;
347  alphas.push_back(vcl_alpha);
348  betas.push_back(vcl_beta);
349  s.clear();
350  }
351 
352  return bisect(alphas, betas);
353  }
354 
363  template< typename MatrixT, typename VectorT >
364  std::vector<
366  >
367  lanczosFRO (MatrixT const& A, VectorT & r, vcl_size_t size, lanczos_tag)
368  {
369  typedef typename viennacl::result_of::value_type<MatrixT>::type NumericType;
370  typedef typename viennacl::result_of::cpu_value_type<NumericType>::type CPU_NumericType;
371 
372  CPU_NumericType temp;
373  CPU_NumericType norm;
374  NumericType vcl_beta;
375  NumericType vcl_alpha;
376  std::vector<CPU_NumericType> alphas, betas;
377  vcl_size_t n = r.size();
378  VectorT u(n), t(n);
379  NumericType inner_rt;
380  boost::numeric::ublas::vector<CPU_NumericType> u_zero(n), s(r.size()), q(n);
381  boost::numeric::ublas::matrix<CPU_NumericType> Q(n, size);
382 
383  long reorths = 0;
384  norm = norm_2(r);
385 
386 
387  for (vcl_size_t i = 0; i < size; i++)
388  {
389  r /= norm;
390 
391  for (vcl_size_t j = 0; j < i; j++)
392  {
395  inner_rt = viennacl::linalg::inner_prod(r,t);
396  r = r - inner_rt * t;
397  reorths++;
398  }
399  temp = viennacl::linalg::norm_2(r);
400  r = r / temp;
401  vcl_beta = temp * norm;
404 
405  u += viennacl::linalg::prod(A, r);
406  vcl_alpha = viennacl::linalg::inner_prod(u, r);
407  r = u - vcl_alpha * r;
408  norm = viennacl::linalg::norm_2(r);
411  u = - norm * t;
412  alphas.push_back(vcl_alpha);
413  betas.push_back(vcl_beta);
414  }
415 
416  return bisect(alphas, betas);
417  }
418 
419 } // end namespace detail
420 
428 template<typename MatrixT>
429 std::vector< typename viennacl::result_of::cpu_value_type<typename MatrixT::value_type>::type >
430 eig(MatrixT const & matrix, lanczos_tag const & tag)
431 {
432  typedef typename viennacl::result_of::value_type<MatrixT>::type NumericType;
433  typedef typename viennacl::result_of::cpu_value_type<NumericType>::type CPU_NumericType;
434  typedef typename viennacl::result_of::vector_for_matrix<MatrixT>::type VectorT;
435 
436  boost::mt11213b mt;
437  boost::normal_distribution<CPU_NumericType> N(0, 1);
438  boost::bernoulli_distribution<CPU_NumericType> B(0.5);
439  boost::triangle_distribution<CPU_NumericType> T(-1, 0, 1);
440 
441  boost::variate_generator<boost::mt11213b&, boost::normal_distribution<CPU_NumericType> > get_N(mt, N);
442  boost::variate_generator<boost::mt11213b&, boost::bernoulli_distribution<CPU_NumericType> > get_B(mt, B);
443  boost::variate_generator<boost::mt11213b&, boost::triangle_distribution<CPU_NumericType> > get_T(mt, T);
444 
445  std::vector<CPU_NumericType> eigenvalues;
446  vcl_size_t matrix_size = matrix.size1();
447  VectorT r(matrix_size);
448  std::vector<CPU_NumericType> s(matrix_size);
449 
450  for (vcl_size_t i=0; i<s.size(); ++i)
451  s[i] = 3.0 * get_B() + get_T() - 1.5;
452 
454 
455  vcl_size_t size_krylov = (matrix_size < tag.krylov_size()) ? matrix_size
456  : tag.krylov_size();
457 
458  switch (tag.method())
459  {
461  eigenvalues = detail::lanczosPRO(matrix, r, size_krylov, tag);
462  break;
464  eigenvalues = detail::lanczosFRO(matrix, r, size_krylov, tag);
465  break;
467  eigenvalues = detail::lanczos(matrix, r, size_krylov, tag);
468  break;
469  }
470 
471  std::vector<CPU_NumericType> largest_eigenvalues;
472 
473  for (vcl_size_t i = 1; i<=tag.num_eigenvalues(); i++)
474  largest_eigenvalues.push_back(eigenvalues[size_krylov-i]);
475 
476 
477  return largest_eigenvalues;
478 }
479 
480 
481 
482 
483 } // end namespace linalg
484 } // end namespace viennacl
485 #endif
int method() const
Returns the reorthogonalization method.
Definition: lanczos.hpp:100
T norm_2(std::vector< T, A > const &v1)
Definition: norm_2.hpp:86
A reader and writer for the matrix market format is implemented here.
vcl_size_t krylov_size() const
Returns the size of the kylov space.
Definition: lanczos.hpp:94
Generic interface for the l^2-norm. See viennacl/linalg/vector_operations.hpp for implementations...
void method(int met)
Sets the reorthogonalization method.
Definition: lanczos.hpp:97
Generic interface for matrix-vector and matrix-matrix products. See viennacl/linalg/vector_operations...
std::vector< typename viennacl::result_of::cpu_value_type< typename MatrixT::value_type >::type > lanczosPRO(MatrixT const &A, VectorT &r, vcl_size_t size, lanczos_tag const &tag)
Implementation of the Lanczos PRO algorithm.
Definition: lanczos.hpp:127
lanczos_tag(double factor=0.75, vcl_size_t numeig=10, int met=0, vcl_size_t krylov=100)
The constructor.
Definition: lanczos.hpp:73
A dense matrix class.
Definition: forwards.h:374
viennacl::enable_if< viennacl::is_stl< typename viennacl::traits::tag_of< VectorT1 >::type >::value, typename VectorT1::value_type >::type inner_prod(VectorT1 const &v1, VectorT2 const &v2)
Definition: inner_prod.hpp:89
Generic interface for the computation of inner products. See viennacl/linalg/vector_operations.hpp for implementations.
std::vector< typename viennacl::result_of::cpu_value_type< typename VectorT::value_type >::type > bisect(VectorT const &alphas, VectorT const &betas)
Implementation of the bisect-algorithm for the calculation of the eigenvalues of a tridiagonal matrix...
Definition: bisect.hpp:75
VectorT prod(std::vector< std::vector< T, A1 >, A2 > const &matrix, VectorT const &vector)
Definition: prod.hpp:91
vcl_size_t size(VectorType const &vec)
Generic routine for obtaining the size of a vector (ViennaCL, uBLAS, etc.)
Definition: size.hpp:144
std::vector< typename viennacl::result_of::cpu_value_type< typename MatrixT::value_type >::type > lanczos(MatrixT const &A, VectorT &r, vcl_size_t size, lanczos_tag)
Implementation of the lanczos algorithm without reorthogonalization.
Definition: lanczos.hpp:312
Implementation of the compressed_matrix class.
void copy_vec_to_vec(viennacl::vector< NumericT > const &src, OtherVectorT &dest)
overloaded function for copying vectors
Definition: bisect.hpp:44
void num_eigenvalues(vcl_size_t numeig)
Sets the number of eigenvalues.
Definition: lanczos.hpp:79
vcl_size_t num_eigenvalues() const
Returns the number of eigenvalues.
Definition: lanczos.hpp:82
std::size_t vcl_size_t
Definition: forwards.h:74
std::vector< typename viennacl::result_of::cpu_value_type< typename MatrixT::value_type >::type > lanczosFRO(MatrixT const &A, VectorT &r, vcl_size_t size, lanczos_tag)
Implementation of the Lanczos FRO algorithm.
Definition: lanczos.hpp:367
T::ERROR_CANNOT_DEDUCE_CPU_SCALAR_TYPE_FOR_T type
Definition: result_of.hpp:238
std::vector< typename viennacl::result_of::cpu_value_type< typename MatrixT::value_type >::type > eig(MatrixT const &matrix, lanczos_tag const &tag)
Implementation of the calculation of eigenvalues using lanczos.
Definition: lanczos.hpp:430
The vector type with operator-overloads and proxy classes is defined here. Linear algebra operations ...
NumericT max(std::vector< NumericT > const &v1)
Definition: maxmin.hpp:47
void krylov_size(vcl_size_t max)
Sets the size of the kylov space.
Definition: lanczos.hpp:91
float ScalarType
Definition: fft_1d.cpp:42
Implementation of the algorithm for finding eigenvalues of a tridiagonal matrix.
double factor() const
Returns the exponent.
Definition: lanczos.hpp:88
vector_expression< const matrix_base< NumericT, F >, const unsigned int, op_column > column(const matrix_base< NumericT, F > &A, unsigned int j)
Definition: matrix.hpp:861
void factor(double fct)
Sets the exponent of epsilon.
Definition: lanczos.hpp:85
A tag for the lanczos algorithm.
Definition: lanczos.hpp:54