基于GSL的QR分解的空间基础

时间:2016-08-05 07:07:25

标签: c++ c matrix linear-algebra gsl

我正在尝试使用GSL获得相对较大的矩阵A^T的零空间的基础。到目前为止,我一直在提取对应于消失的奇异值的SVD的右奇异向量,但是对于我感兴趣的矩阵的大小来说这变得太慢了。

我知道可以在m-r的QR分解中将零空间提取为Q矩阵的最后A列,其中rA的等级但是我不确定排名分析是如何工作的。

这是我第一次尝试使用gsl_linalg_QR_decomp

int m = 4;
int n = 3;
gsl_matrix* A  = gsl_matrix_calloc(m,n);
gsl_matrix_set(A, 0,0, 3);gsl_matrix_set(A, 0,1, 6);gsl_matrix_set(A, 0,2, 1);
gsl_matrix_set(A, 1,0, 1);gsl_matrix_set(A, 1,1, 2);gsl_matrix_set(A, 1,2, 1);
gsl_matrix_set(A, 2,0, 1);gsl_matrix_set(A, 2,1, 2);gsl_matrix_set(A, 2,2, 1);
gsl_matrix_set(A, 3,0, 1);gsl_matrix_set(A, 3,1, 2);gsl_matrix_set(A, 3,2, 1);
std::cout<<"A:"<<endl;
for(int i=0;i<m;i++){ for(int j=0;j<n;j++) printf(" %5.2f",gsl_matrix_get(A,i,j)); std::cout<<std::endl;}

gsl_matrix* Q = gsl_matrix_alloc(m,m);
gsl_matrix* R = gsl_matrix_alloc(m,n);
gsl_vector* tau = gsl_vector_alloc(std::min(m,n));
gsl_linalg_QR_decomp(A, tau);
gsl_linalg_QR_unpack(A, tau, Q, R);
std::cout<<"Q:"<<endl;
for(int i=0;i<m;i++){ for(int j=0;j<m;j++) printf(" %5.2f",gsl_matrix_get(Q,i,j)); std::cout<<std::endl;}
std::cout<<"R:"<<endl;
for(int i=0;i<m;i++){ for(int j=0;j<n;j++) printf(" %5.2f",gsl_matrix_get(R,i,j)); std::cout<<std::endl;}

此输出

A:
  3.00  6.00  1.00
  1.00  2.00  1.00
  1.00  2.00  1.00
  1.00  2.00  1.00
Q:
 -0.87 -0.29  0.41 -0.00
 -0.29  0.96  0.06 -0.00
 -0.29 -0.04 -0.64 -0.71
 -0.29 -0.04 -0.64  0.71
R:
 -3.46 -6.93 -1.73
  0.00  0.00  0.58
  0.00  0.00 -0.82
  0.00  0.00  0.00

但我不确定如何从中计算排名r。我的第二次尝试使用gsl_linalg_QRPT_decomp,用

替换最后一部分
gsl_vector* tau = gsl_vector_alloc(std::min(m,n));
gsl_permutation* perm = gsl_permutation_alloc(n);
gsl_vector* norm = gsl_vector_alloc(n);
int* sign = new int(); *sign = 1;
gsl_linalg_QRPT_decomp2(A, Q, R, tau, perm, sign, norm );
std::cout<<"Q:"<<endl;
for(int i=0;i<m;i++){ for(int j=0;j<m;j++) printf(" %5.2f",gsl_matrix_get(Q,i,j)); std::cout<<std::endl;}
std::cout<<"R:"<<endl;
for(int i=0;i<m;i++){ for(int j=0;j<n;j++) printf(" %5.2f",gsl_matrix_get(R,i,j)); std::cout<<std::endl;}
std::cout<<"Perm:"<<endl;
for(int i=0;i<n;i++) std::cout<<" "<<gsl_permutation_get(perm,i);

导致

Q:
 -0.87  0.50  0.00  0.00
 -0.29 -0.50 -0.58 -0.58
 -0.29 -0.50  0.79 -0.21
 -0.29 -0.50 -0.21  0.79
R:
 -6.93 -1.73 -3.46
  0.00 -1.00  0.00
  0.00  0.00  0.00
  0.00  0.00  0.00
Perm:
 1 2 0

在这里,我认为排名是R中非零对角线元素的数量,但我不确定要从Q中提取哪些元素。我应该采取哪种方法?

1 个答案:

答案 0 :(得分:0)

对于4×3 A,“零空间”将由3维向量组成,而A上的QR分解仅为您提供4维向量。 (当然,您可以对A M进行推广,其中N×M N&gt; A

因此,对Q gsl_linalg_QR_decomp现在为3×3的转置进行QR分解。

在IPython中使用Python / Numpy绘制流程(抱歉,我似乎无法弄清楚如何使用PyGSL调用In [16]: import numpy as np In [17]: A = np.array([[3.0, 6, 1], [1.0, 2, 1], [1.0, 2, 1], [1.0, 2, 1]]) In [18]: Q, R = np.linalg.qr(A.T) # <---- A.T means transpose(A) In [19]: np.diag(R) Out[19]: array([ -6.78232998e+00, 6.59380473e-01, 2.50010468e-17]) In [20]: np.round(Q * 1000) / 1000 # <---- Q to 3 decimal places Out[20]: array([[-0.442, -0.066, -0.894], [-0.885, -0.132, 0.447], [-0.147, 0.989, 0. ]]) ):

Out[19]

第19个输出(即np.diag(R)A的结果)告诉我们Out[20]的列级别为2.并查看Q的第3列([-0.894, 0.447, 0]到小数点后三位),我们看到返回了正确的答案:[1, 0.5, 0]A成正比,我们知道这是正确的,因为{{1}的前两列是线性依赖的。

你能用更大的矩阵检查transpose(A)的QR分解是否为你当前的SVD方法提供了等效的零空间?