【问题标题】:Null space basis from QR decomposition with GSL使用 GSL 的 QR 分解的零空间基
【发布时间】:2016-08-05 07:07:25
【问题描述】:

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

我知道零空间可以提取为A的QR分解中Q矩阵的最后m-r列,其中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 中提取哪些元素。我应该采取哪种方法?

【问题讨论】:

  • 你的A 矩阵是否总是像这个例子一样高?
  • 我所追求的零空间的矩阵通常很宽,所以转置总是像这个例子一样高。

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


【解决方案1】:

对于 4×3 A,“零空间”将由 3 维向量组成,而 A 上的 QR 分解只为您提供 4 维向量。 (当然,您可以将其概括为A,大小为M×N,其中M > N。)

因此,对A转置进行QR分解,其Q现在是3×3。

在 IPython 中使用 Python/Numpy 绘制流程(抱歉,我似乎无法弄清楚如何使用 PyGSL 调用 gsl_linalg_QR_decomp):

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.   ]])

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

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

【讨论】:

  • 啊,从我的描述中并不清楚我在 A^T 的空空间之后,这就是我使用 A 的 QR 的原因。如果你转置你会得到np.diag(R) =&gt; array([-6.93, 0.00, -0.82]) ,并且您说这足以得出排名为 2 (rank=len([d for d in np.diag(R) if d&gt;0.0001]))
猜你喜欢
  • 2018-08-09
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-01
  • 2019-04-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多