在本征

时间:2019-07-11 13:21:00

标签: eigen

可以说我有一个小的稀疏矩阵B。 我想建立一个更大的稀疏矩阵,像

BtB      0
0     (BtB)^-1

我想知道Eigen是否提供某些功能来汇编这样的内容。我一直在搜索,却一无所获。我可以使用的一种选择是计算运算,提取三元组并根据三元组组装矩阵。有没有更简单的方法?

1 个答案:

答案 0 :(得分:0)

如果要显式构建稀疏块矩阵(有正当的理由!),这就是我使用的方法(仅适用于列主行-易于适应行主行)。在这里,sparse_stack_v意味着垂直“堆叠”两个矩阵。 sparse_stack_h同样用于水平“堆叠”两个稀疏矩阵。 sparse_stack_h_inplace是一种更有效的操作,因为您可以为左矩阵重用大多数稀疏结构(并覆盖它)。

void sparse_stack_v(
    const SparseMatrix<Scalar, ColMajor, StorageIndex>& top,
    const SparseMatrix<Scalar, ColMajor, StorageIndex>& bottom,
    SparseMatrix<Scalar, ColMajor, StorageIndex>& stacked)
{
    assert(top.cols() == bottom.cols());
    stacked.resize(top.rows() + bottom.rows(), top.cols());
    stacked.resizeNonZeros(top.nonZeros() + bottom.nonZeros());

    StorageIndex i = 0;

    for (StorageIndex col = 0; col < top.cols(); col++)
    {
        stacked.outerIndexPtr()[col] = i;

        for (StorageIndex j = top.outerIndexPtr()[col]; j < top.outerIndexPtr()[col + 1]; j++, i++)
        {
            stacked.innerIndexPtr()[i] = top.innerIndexPtr()[j];
            stacked.valuePtr()[i] = top.valuePtr()[j];
        }

        for (StorageIndex j = bottom.outerIndexPtr()[col]; j < bottom.outerIndexPtr()[col + 1]; j++, i++)
        {
            stacked.innerIndexPtr()[i] = (StorageIndex)top.rows() + bottom.innerIndexPtr()[j];
            stacked.valuePtr()[i] = bottom.valuePtr()[j];
        }
    }
    stacked.outerIndexPtr()[top.cols()] = i;
    assert(stacked.isCompressed());
}

template<typename Scalar, typename StorageIndex>
void sparse_stack_h(
    const SparseMatrix<Scalar, ColMajor, StorageIndex>& left,
    const SparseMatrix<Scalar, ColMajor, StorageIndex>& right,
    SparseMatrix<Scalar, ColMajor, StorageIndex>& stacked)
{
    assert(left.rows() == right.rows());

    stacked.resize(left.rows(), left.cols() + right.cols());
    stacked.resizeNonZeros(left.nonZeros() + right.nonZeros());

    std::copy(left.innerIndexPtr(), left.innerIndexPtr() + left.nonZeros(), stacked.innerIndexPtr());
    std::copy(right.innerIndexPtr(), right.innerIndexPtr() + right.nonZeros(), stacked.innerIndexPtr() + left.nonZeros());

    std::copy(left.valuePtr(), left.valuePtr() + left.nonZeros(), stacked.valuePtr());
    std::copy(right.valuePtr(), right.valuePtr() + right.nonZeros(), stacked.valuePtr() + left.nonZeros());

    std::copy(left.outerIndexPtr(), left.outerIndexPtr() + left.cols(), stacked.outerIndexPtr());//dont need the last entry of A.outerIndexPtr() -- total length is AB.cols() + 1 = A.cols() + B.cols() + 1
    std::transform(right.outerIndexPtr(), right.outerIndexPtr() + right.cols() + 1, stacked.outerIndexPtr() + left.cols(), [&](StorageIndex i) { return i + left.nonZeros(); });

    assert(stacked.isCompressed());
}

template<typename Scalar, typename StorageIndex>
void sparse_stack_h_inplace(
    SparseMatrix<Scalar, ColMajor, StorageIndex>& left,
    const SparseMatrix<Scalar, ColMajor, StorageIndex>& right)
{
    assert(left.rows() == right.rows());

    const StorageIndex leftcol = (StorageIndex)left.cols();
    const StorageIndex leftnz = (StorageIndex)left.nonZeros();

    left.conservativeResize(left.rows(), left.cols() + right.cols());
    left.resizeNonZeros(left.nonZeros() + right.nonZeros());

    std::copy(right.innerIndexPtr(), right.innerIndexPtr() + right.nonZeros(), left.innerIndexPtr() + leftnz);
    std::copy(right.valuePtr(), right.valuePtr() + right.nonZeros(), left.valuePtr() + leftnz);
    std::transform(right.outerIndexPtr(), right.outerIndexPtr() + right.cols() + 1, left.outerIndexPtr() + leftcol, [&](StorageIndex i) { return i + leftnz; });

    assert(left.isCompressed());
}

如果要“填充”零的稀疏矩阵,只需将矩阵与适当大小的空稀疏矩阵堆叠即可。