基于Givens旋转的QR分解算法

时间:2012-11-18 06:42:51

标签: matlab qr-decomposition

我在MATLAB中编码QR分解算法,只是为了确保我的机制正确。这是主要功能的代码:

    function [Q,R] = QRgivens(A)
        n = length(A(:,1));
        Q = eye(n);
        R = A;

        for j = 1:(n-1)
            for i = n:(-1):(j+1)
                G = eye(n);
                [c,s] = GivensRotation( A(i-1,j),A(i,j) );
                G(i-1,(i-1):i) = [c s];
                G(i,(i-1):i)   = [-s c];
                Q = Q*G';
                R = G*R;
            end
        end
    end

子函数GivensRotation如下:

    function [c,s] = GivensRotation(a,b)
        if b == 0
            c = 1;
            s = 0;
        else
            if abs(b) > abs(a)
                r = -a / b;
                s = 1 / sqrt(1 + r^2);
                c = s*r;
            else
                r = -b / a;
                c = 1 / sqrt(1 + r^2);
                s = c*r;
            end
        end
    end

我已经完成了研究,我很确定这是实现这种分解的最直接的方法之一,特别是在MATLAB中。但是当我在矩阵A上测试它时,产生的R不应该是正确的三角形。 Q是正交的,并且Q * R = A,因此算法正在做一些正确的事情,但它没有产生完全正确的分解。也许我一直在盯着这个问题太长时间,但是对于我所忽视的内容的任何见解都会受到赞赏。

1 个答案:

答案 0 :(得分:11)

这似乎有更多的错误, 我所看到的:

  1. 你应该使用[c,s] = GivensRotation(R(i-1,j),R(i,j)); (注意,R而不是A)
  2. 原始乘法Q = Q * G'; R = G * R是正确的。
  3. r = a / b且r = b / a(没有减号,不确定是否重要)
  4. G([i-1,i],[i-1,i])= [c -s; s c];
  5. 这是一个示例代码,似乎有效。

    第一个文件,

    % qrgivens.m
    function [Q,R] = qrgivens(A)
      [m,n] = size(A);
      Q = eye(m);
      R = A;
    
      for j = 1:n
        for i = m:-1:(j+1)
          G = eye(m);
          [c,s] = givensrotation( R(i-1,j),R(i,j) );
          G([i-1, i],[i-1, i]) = [c -s; s c];
          R = G'*R;
          Q = Q*G;
        end
      end
    
    end
    

    和第二个

    % givensrotation.m
    function [c,s] = givensrotation(a,b)
      if b == 0
        c = 1;
        s = 0;
      else
        if abs(b) > abs(a)
          r = a / b;
          s = 1 / sqrt(1 + r^2);
          c = s*r;
        else
          r = b / a;
          c = 1 / sqrt(1 + r^2);
          s = c*r;
        end
      end
    
    end