Dukales

QR decomposition (Householder transformation) for m*n matrix

Jan 3rd, 2015
329
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.61 KB | None | 0 0
  1. #include <iostream>
  2. #include <ostream>
  3. #include <valarray>
  4. #include <algorithm>
  5. #include <numeric>
  6. #include <utility>
  7. #include <functional>
  8. #include <limits>
  9.  
  10. #include <cstdlib>
  11. #include <cassert>
  12.  
  13. using value_type = double;
  14. using vector = std::valarray< value_type >; // column-vector
  15. using matrix = std::valarray< vector >;
  16.  
  17. std::ostream &
  18. operator << (std::ostream & out, vector const & v)
  19. {
  20.     for (value_type const & x : v) {
  21.         out << x << ' ';
  22.     }
  23.     return out << '\n';
  24. }
  25.  
  26. std::ostream &
  27. operator << (std::ostream & out, matrix const & a)
  28. {
  29.     std::size_t const m = a[0].size();
  30.     std::size_t const n = a.size();
  31.     for (std::size_t i = 0; i < m; ++i) {
  32.         for (std::size_t j = 0; j < n; ++j) {
  33.             out << a[j][i] << ' ';
  34.         }
  35.         out << '\n';
  36.     }
  37.     return out << '\n';
  38. }
  39.  
  40. value_type const eps = std::numeric_limits< value_type >::epsilon();
  41. value_type const zero = value_type(0);
  42. value_type const one = value_type(1);
  43.  
  44. int
  45. main()
  46. {
  47.     matrix a{{1.0, -4.0, 4.0, -11.0}, {2.0, 10.0, 5.0, 13.0}, {3.0, -1.0, 7.0, 0.0}};
  48.     std::cout << "A:\n" << a;
  49.  
  50.     std::size_t const m = a[0].size();
  51.     std::size_t const n = a.size();
  52.     vector rtrace(zero, n);
  53.     for (std::size_t j = 0; j < n; ++j) { // Householder itself
  54.         value_type norm = zero;
  55.         vector & qr_j = a[j];
  56.         for (std::size_t i = j; i < m; ++i) {
  57.             value_type const & qrij = qr_j[i];
  58.             norm += qrij * qrij;
  59.         }
  60.         using std::sqrt;
  61.         norm = sqrt(norm);
  62.         value_type & qrjj = qr_j[j];
  63.         value_type & dj = rtrace[j];
  64.         dj = (zero < qrjj) ? -norm : norm;
  65.         using std::abs;
  66.         value_type f = norm * (norm + abs(qrjj));
  67.         assert(eps < f);
  68.         f = one / sqrt(std::move(f));
  69.         qrjj -= dj;
  70.         for (std::size_t k = j; k < m; ++k) {
  71.             qr_j[k] *= f;
  72.         }
  73.         for (std::size_t i = j + 1; i < n; ++i) {
  74.             vector & qr_i = a[i];
  75.             value_type dot_product = zero;
  76.             for (std::size_t k = j; k < m; ++k) {
  77.                 dot_product += qr_j[k] * qr_i[k];
  78.             }
  79.             for (std::size_t k = j; k < m; ++k) {
  80.                 qr_i[k] -= qr_j[k] * dot_product;
  81.             }
  82.         }
  83.     }
  84.     std::cout << "QR:\n" << a;
  85.     std::cout << "trace(R):\n" << rtrace;
  86.  
  87.     matrix q{{1.0, 0.0, 0.0, 0.0},
  88.              {0.0, 1.0, 0.0, 0.0},
  89.              {0.0, 0.0, 1.0, 0.0}};
  90.     for (std::size_t i = 0; i < n; ++i) {
  91.         vector & qi = q[i];
  92.         std::size_t j = n;
  93.         while (0 < j) {
  94.             --j;
  95.             vector & qr_j = a[j];
  96.             value_type s_ = zero;
  97.             for (std::size_t k = j; k < m; ++k) {
  98.                 s_ += qr_j[k] * qi[k];
  99.             }
  100.             for (std::size_t k = j; k < m; ++k) {
  101.                 qi[k] -= qr_j[k] * s_;
  102.             }
  103.         }
  104.     }
  105.     std::cout << "Q:\n" << q;
  106.  
  107.     matrix r{{0.0, 0.0, 0.0},
  108.              {0.0, 0.0, 0.0},
  109.              {0.0, 0.0, 0.0}};
  110.     for (std::size_t i = 0; i < n; ++i) {
  111.         r[i][i] = rtrace[i];
  112.         for (std::size_t j = 0; j < i; ++j) {
  113.             r[i][j] = a[i][j];
  114.         }
  115.     }
  116.     std::cout << "R:\n" << r;
  117.  
  118.     matrix qr{{0.0, 0.0, 0.0, 0.0},
  119.               {0.0, 0.0, 0.0, 0.0},
  120.               {0.0, 0.0, 0.0, 0.0}};
  121.     for (std::size_t i = 0; i < m; ++i) {
  122.         for (std::size_t j = 0; j < n; ++j) {
  123.             for (std::size_t k = 0; k < n; ++k) {
  124.                 qr[j][i] += q[k][i] * r[j][k];
  125.             }
  126.         }
  127.     }
  128.     std::cout << "Q * R:\n" << qr << std::flush;
  129.     return EXIT_SUCCESS;
  130. }
Advertisement
Add Comment
Please, Sign In to add comment