为什么 QR 分解不能正常工作? (Lapacke,复杂的情况)

Why doesn't QR decomposition work correctly? (Lapacke, complex case)

我用的是Lapacke。我正在尝试在 C 中对复杂数据进行 QR 分解。为此,我编写了函数(基于 Haatschii 代码 ):

// Q - input: matrix that we expand / output: Q matrix
// R - output: R matrix
// rows - input: number of rows of Q
// columns - input: number of columns of Q
// rows >= columns condition is always met
void QR(lapack_complex_double * Q, lapack_complex_double * R, size_t rows, size_t columns){
    size_t i;
    lapack_complex_double* tau = malloc(columns*sizeof(lapack_complex_double));
    LAPACKE_zgeqrf(LAPACK_ROW_MAJOR, (int) rows, (int) columns, Q, (int) columns, tau); // returns the Q, R in a packed format
    // Copy the upper triangular Matrix R (columns x columns).
    for(i = 0; i < columns; ++i)
        memcpy(R+i*columns+i, Q+i*columns+i, (columns-i)*sizeof(lapack_complex_double));
    LAPACKE_zungqr(LAPACK_ROW_MAJOR, (int) rows, (int) columns, (int) columns, Q, (int) columns, tau); // returns the Q
    free(tau);
}

值得注意的是,Alireza 的作者在函数 znugqr, but however he switched to the function zunmqr and it seems that happiness has come () 上也有问题。我相信我的问题也与 LAPACKE_zungqr 有关,因为矩阵 R 与其他方法相同,因此 LAPACKE_zgeqrf 成功运行。

但最后,将相似的结果(QR 分解)与 Mathematica(QRDecomposition 函数)和 Python(numpy.linalg.qr 函数)进行比较,我发现矩阵 Q 是不同,而矩阵R相同

输入矩阵,为简单起见5×5:

1 + 3j  6 + 8j    11 + 13j  16 + 18j  21 + 23j  
2 + 4j  7 + 9j    12 + 14j  17 + 19j  22 + 24j  
3 + 5j  8 + 10j   13 + 15j  18 + 20j  23 + 25j  
4 + 6j  9 + 11j   14 + 16j  19 + 21j  24 + 26j  
5 + 7j  10 + 12j  15 + 17j  20 + 22j  25 + 27j

输出Q矩阵(来自我的C代码): 前 3 列:

-0.07254 - 0.21764j    -0.61558 - 0.41039j     0.519770 - 0.06712j
-0.14509 - 0.29019j    -0.35909 - 0.25649j    -0.59817 + 0.211099j
-0.21764 - 0.36273j    -0.10259 - 0.10259j     0.035755 - 0.18619j
-0.29019 - 0.43528j     0.153896 + 0.051298j  -0.35605 + 0.007600j
-0.36273 - 0.50783j     0.410391 + 0.205195j   0.398709 + 0.034623j

最后 2 列:

-0.12316 - 0.06327j    -0.11940 + 0.303152j
 0.221078 + 0.491045j   0.084589 - 0.02148j
-0.06231 - 0.31146j     0.119483 - 0.80553j
-0.04594 - 0.59711j    -0.01512 + 0.462905j
 0.010343 + 0.480803j  -0.06954 + 0.060958j

输出Q矩阵(来自Python代码):

-0.11670 - 0.06185j    -0.13105 + 0.301181j
 0.223111 + 0.487988j   0.096454 - 0.02009j
-0.08117 - 0.30874j     0.138515 - 0.80184j
-0.04015 - 0.59906j    -0.04217 + 0.459232j
 0.014923 + 0.481676j  -0.06174 + 0.061519j

(这里我只列出了这个矩阵的最后两列。前三列是相同的)。

我计算了这些矩阵中各列的最大差值和平均差值。结论是这样的:前三列相差10^-11,后两列相差10^-310^-2(肉眼可见的区别) ).

随着矩阵大小的增加,观察到差异增加,通常前 2-3 列重合。

也许有人可以帮助我?

输入矩阵 A 为 5x5,但秩为 2。前两列是线性独立的,而 A 的后三列是前两列的线性组合。

对于 QR 分解,这意味着 Q 的最后三列没有唯一性。QR 分解实现(例如 LAPACK、numpy 等)可以 return 任何三列(1) 互正交和 (2) 在 A^(perp) 中,这是正确答案。有很多正确答案! The解不是唯一的。

如果您想检查由 LAPACK 编辑的 Q 和 R return(或任何 QR 因式分解实现),您可以 (1) 计算 Q'*Q 并检查您是否得到5x5 单位矩阵,(请使用 BLAS HERK 函数)和 (2) 计算 Q'*A 并检查您是否具有 5x5 上三角矩阵 R(由 QR 编辑 return)。在您的情况下,您应该看到 R 的最后 3 行都是零,这表明 A 的最后三列是前两列的线性组合。要计算 Q'*A,您可以使用 BLAS GEMM。

我从 LAPACK 获取了您的输入 A 和输出 Q,并为您检查了 Q'*Q 是恒等式,Q'*R 是上三角,最后三行全为零。所以 LAPACK 的 Q 输出对我来说看起来不错。是的,这个 Q 不同于 return 由另一个实现编辑的内容,这是完全可能的。

一般来说,我们通过检查以下内容来检查 QR 分解的质量:(1) || A - 二维码 || / ||一个||很小, (2) ||我 - Q^T Q ||很小,R 是上三角。 (取任何容易计算的范数。)

检查两个代码 return 相同的输出不是一个好主意。由于两个原因导致输出 Q 和 R 不唯一:(1)当 A 秩亏时,请参见您给出的示例; (2) 对于任何 j,只要您相应地缩放 R 的 j-th 行,对于 Q 的 j-th 列,任何具有复数模数 1 的列缩放都是可能的。这会更改 Q 和 R 因子,但仍然存在有效的 Q 和 R 因子。

此外,假设您强制 R 的所有对角线元素为非负实数,(通过适当地重新缩放 Q 的列和 R 的列,)并且 A 是满秩的,那么您会期望 Q 和R. 然而,检查 (Q,R) 对是否接近另一个与计算 Q 和 R 以进行 QR 因式分解的条件数有关,因此您可以看到相距很远的对(前向误差),即使它们具有良好的后向误差质量。