如何有效地仅反转分配矩阵的一部分

How to efficiently invert only part of an allocated matrix

我有一个算法可以分配一个预定义大小为 N x N 的复数双精度矩阵 "A"。元素最初为零。我还分配了大小为 N x N 的矩阵来存储逆矩阵 "A_inv"。 在算法期间,"A" 的元素被填充。在每次迭代 i 中,我最终得到一个大小为 i x i 的子矩阵。所以第二次迭代看起来像这样,其中 N=4:

| x00 x01 0.0 0.0 |
| x10 x11 0.0 0.0 |
| 0.0 0.0 0.0 0.0 |
| 0.0 0.0 0.0 0.0 |

其中 x 表示某个非零值。现在我希望反转矩阵的非零部分(本例中为 2x2 矩阵)。 到目前为止,我一直在通过以下方式进行此操作:

  1. 将"A"的非零元素复制到2x2 gsl矩阵
  2. 使用 gsl LU 分解来反转 2x2 gsl 矩阵
  3. 将2x2倒矩阵复制到A_inv

这种方法的问题是我必须在每次迭代中复制矩阵两次。一次是一个较小的 n x n gsl 矩阵,一次是将生成的倒置 nxn gsl 矩阵复制到 A_inv.

我想知道是否有人知道更直接的方法。有没有办法使用一些 gsl 函数只反转矩阵的一部分并忽略任何零元素? 像这样说:

A = NxN matrix
A_inv = invert_submatrix(A,n,n)

其中 n < N。 这里 invert_submatrix() 将只考虑 A 的 n x n 部分。此外,原始矩阵 "A" 不能被这个反转改变。 也许最后的需求使得无论如何都必须复制矩阵,在这种情况下它不会比我现在做的更有效率。也就是说,gsl 算法往往比我通常想出的任何算法都高效得多。所以对此的想法仍然非常受欢迎。

遗憾的是,正如 GSL 所做的那样,它是 LU 分解,如果您要求不修改子矩阵,我不确定是否可以先将子矩阵从 A 中复制出来。但是,您可以使用 matrix view 直接从 LU 分解构造逆函数,而不必构造它然后复制它。

gsl_matrix *invert_submatrix( const gsl_matrix *m, size_t sub_size )
{
    gsl_matrix *inv = gsl_matrix_calloc( m->size1, m->size2 );

    // Create views onto the submatrices we care about 
    gsl_matrix_const_view m_sub_view = 
        gsl_matrix_const_submatrix(m, 0, 0, sub_size, sub_size);

    gsl_matrix_view inv_sub_view = 
        gsl_matrix_submatrix(inv, 0, 0, sub_size, sub_size);

    const gsl_matrix *m_sub = &m_sub_view.matrix;
    gsl_matrix *inv_sub = &inv_sub_view.matrix;

    // Create a matrix for the LU decomposition as GSL does this inplace.
    gsl_permutation *perm = gsl_permutation_alloc(sub_size);
    gsl_matrix *LU = gsl_matrix_alloc(sub_size, sub_size);
    gsl_matrix_memcpy(LU, m_sub);

    int s;
    gsl_linalg_LU_decomp(LU, perm, &s);
    gsl_linalg_LU_invert(LU, perm, inv_sub);

    gsl_matrix_free(LU);
    gsl_permutation_free(perm);

    return inv;
}