用 mkl LAPACK 求解矩阵的零空间

计算科学 线性求解器 拉帕克 英特尔-mkl
2021-12-07 14:21:00

我想找到一个解决方案xA=0, 在哪里A是一个方阵。我知道大多数 LAPACK 例程都可以解决Ax=b. 所以我拿AT作为一个,并设置b=0. 我有一个额外的限制Σx=1.因此,我添加了额外的一行onesAT和一个oneb. 这也允许避免琐碎的解决方案,其中x=0.

这种方法在 Octave 中运行良好,但我正在努力用 LAPACK 来实现它。我不断得到info=4,这意味着我的第四个因素U在里面LU因式分解AT与一排ones单数发生这种情况是因为我的最后一行是ones.

有没有什么好办法解决xA=0? 我应该在我的真实数据中添加,A是稀疏的。

这是我在 C 中的失败尝试,其中b=[0,0,0,1].

float *A, *b;
/* Ax = b
 * Ax = xT(A)   //transpose
 * A is m x m   //matrix   
 * b is m x 1  //vector
 * x is m x 1   //vector
 */
int m = 3;
int scale = 1;
A = (float *)mkl_malloc(m*m,32);
A[0]=-5;A[1]= 2;A[2]= 3;
A[3]= 4;A[4]= -10;A[5]= 6;
A[6]= 7;A[7]=8;A[8]= -15;

b = (float*)mkl_malloc(m+1,32);
for (int i = 0; i < m; i++) {
    b[i]=0.0;
}
b[m]=1.0;

int matrix_order = LAPACK_ROW_MAJOR;

int ipiv[m+1];

int info;
//transpose and add a row of ones
float * Acopy = (float*)mkl_malloc((m+1)*m,32);
mkl_somatcopy('R','T',m,m,scale,A,m,Acopy,m);
//assign last row of ones
for (int i = 0; i < m; i++){
    int p = m*m+i;
    Acopy[p]=1.0;
}

printf("Original\n");
print_matrix(A, m, m );
printf("Transpose with ones\n");
print_matrix(Acopy, m+1, m );

info = LAPACKE_sgesv(matrix_order,m+1,1,Acopy,m+1,ipiv,b,1);

printf("$?=%d\n",info);

print_matrix(b, m+1, 1 );
return 0;

谢谢你。

1个回答

没有理由附加一行 1。您应该只在AT,最后一列Q应该在零空间中。这具有额外的优势,即对角线上最后一个元素的相对大小R让您了解解决方案的独特性。更好的是执行奇异值分解A=UΣVT. 然后,最后一列U是一个单一的解决方案xA=0. 您可以简单地规范化以实现x=1然后。

请注意,您不能只在底部附加一行A从那时起,您就有了一个非方形系统。您可能可以使用 SGELS(或任何其他变体)通过最小二乘法解决该问题。这通常不如我之前给出的两个建议那么健壮,尽管它明确地强制规范化。

编辑:注意速度和稳定性。我猜 QR 比 SVD 稍微快一点,而 SVD 在数值上更稳定(尽管实际上,它们足够稳定,人们不必担心)。我没有很好的速度感,因为 QR 中更复杂的旋转速度较慢。最后请注意,这些方法仅适用于密集矩阵。如果你想要在稀疏情况下工作的东西,你可以尝试逆幂迭代A. 这应该只要A不完全是单数(基本上从不会在数字上发生)。