[Eigen中文文档] 就地矩阵分解

简介: 从 Eigen 3.3 开始,LU、Cholesky 和 QR 分解可以就地操作,即直接在给定的输入矩阵内操作。当处理大矩阵时,或者当可用内存非常有限(嵌入式系统)时,此功能特别有用。

文档总目录

英文原文(Inplace matrix decompositions)

从 Eigen 3.3 开始,LUCholeskyQR 分解可以就地操作,即直接在给定的输入矩阵内操作。当处理大矩阵时,或者当可用内存非常有限(嵌入式系统)时,此功能特别有用。

为此,必须使用 Ref<> 矩阵类型实例化相应的分解类,并且必须使用输入矩阵作为参数构造分解对象。作为一个例子,让我们考虑一个带有部分旋转的就地 LU 分解。

声明一个 2x2 矩阵 A:

 Eigen::MatrixXd A(2,2); 
 A << 2, -1, 
      1, 3;
 std::cout << "Here is the input matrix A before decomposition:\n" << A << "\n";

输出:

Here is the input matrix A before decomposition:
 2 -1
 1  3

然后,声明就地 LU 分解对象 lu,并检查矩阵 A 的内容:

Eigen::PartialPivLU<Eigen::Ref<Eigen::MatrixXd> > lu(A);
std::cout << "Here is the input matrix A after decomposition:\n" << A << "\n";

输出:

Here is the input matrix A after decomposition:
  2  -1
0.5 3.5

在这里,lu 对象计算 LU 因子并将其存储在矩阵 A 所持有的内存中。A 的系数在分解过程中被破坏,并由 LU 因子代替,可以验证:

std::cout << "Here is the matrix storing the L and U factors:\n" << lu.matrixLU() << "\n";

输出:

Here is the matrix storing the L and U factors:
  2  -1
0.5 3.5

然后,可以使用 lu 对象,例如解决 $Ax=b$ 问题:

Eigen::MatrixXd A0(2,2); A0 << 2, -1, 1, 3;
Eigen::VectorXd b(2);    b << 1, 2;
Eigen::VectorXd x = lu.solve(b);
std::cout << "Residual: " << (A0 * x - b).norm() << "\n";

输出:

Residual: 0

由于Alu共享内存,修改矩阵A将使lu无效。可以通过修改内容A并再次尝试解决初始问题来轻松验证:

A << 3, 4, -2, 1;
x = lu.solve(b);
std::cout << "Residual: " << (A0 * x - b).norm() << "\n";

输出:

Residual: 15.8114

请注意,这里没有共享指针,用户需要使输入矩阵 Alu 保持相同的生命周期。

如果想用修改后的 A 更新因式分解,则必须像往常一样调用 compute 方法:

A0 = A; // save A
lu.compute(A);
x = lu.solve(b);
std::cout << "Residual: " << (A0 * x - b).norm() << "\n";

输出:

Residual: 0

请注意,调用 compute 不会更改 lu 对象引用的内存。因此,如果使用不同于 A 的另一个矩阵 A1 调用 compute 方法,则不会修改 A1 的内容。这仍然是 A 的内容,它将用于存储矩阵 A1 的 L 和 U 因子。验证如下:

Eigen::MatrixXd A1(2,2);
A1 << 5,-2,3,4;
lu.compute(A1);
std::cout << "Here is the input matrix A1 after decomposition:\n" << A1 << "\n";

输出:

Here is the input matrix A1 after decomposition:
 5 -2
 3  4

矩阵 A1 没有改变,并且可以求解 $A1*x=b$,也可以不复制 A1 直接求得残差:

x = lu.solve(b);
std::cout << "Residual: " << (A1 * x - b).norm() << "\n";

输出:

Residual: 2.48253e-16

以下是支持这种就地机制的矩阵分解列表:

相关文章
|
XML 并行计算 算法
[Eigen中文文档] 求解稀疏线性系统
在Eigen中,有多种方法可用于求解稀疏系数矩阵的线性系统。由于此类矩阵的特殊表示,必须特别小心以获得良好的性能。本文列出了Eigen中可用的稀疏求解器。还介绍了所有这些线性求解器共同的主要步骤。根据矩阵的属性、所需的准确度,最终用户可以调整这些步骤以提高其代码的性能。请注意,并不需要深入了解这些步骤背后的内容:最后一节介绍了一个基础例程,可轻松使用以获取所有可用求解器的性能洞察。
1084 0
|
存储 算法 NoSQL
[Eigen中文文档] 存储顺序
矩阵和二维数组有两种不同的存储顺序:列优先和行优先。本节解释了这些存储顺序以及如何指定应该使用哪一种。
716 0
|
缓存 测试技术 编译器
[Eigen中文文档] 稠密矩阵分解函数对比
本文介绍了 Eigen 为各种方阵和过约束问题提供的稠密矩阵分解的速度比较。
558 0
|
编译器 索引
[Eigen中文文档] 块操作
本文介绍了块操作。块是matrix或array的部分矩形元素。块表达式既可以用作右值也可以用作左值。与Eigen表达式一样,如果让编译器进行优化,则块操作的运行时间成本为零。
498 0
|
存储 算法 NoSQL
[Eigen中文文档] 稀疏矩阵操作
在许多应用中(例如,有限元方法),通常要处理非常大的矩阵,其中只有少数系数不为零。在这种情况下,可以通过使用仅存储非零系数的特殊表示来减少内存消耗并提高性能。这样的矩阵称为稀疏矩阵。
1066 0
|
Ubuntu 计算机视觉 C++
Ubuntu 20.04 编译 Opencv 4.11,详细步骤(带图)及报错解决,我的踩坑之旅~
Ubuntu 20.04 编译 Opencv 4.11,详细步骤(带图)及报错解决,我的踩坑之旅~
10755 0
|
存储 安全 编译器
[Eigen中文文档] 常见的陷阱
本文将介绍一些Eigen常见的陷阱
844 0
|
安全 编译器 C++
[Eigen中文文档] 矩阵与向量运算
本文章旨在提供有关如何使用 Eigen 在矩阵、向量和标量之间执行算术操作的概述和一些详细信息。
1076 0
|
存储 NoSQL API
[Eigen中文文档] Matrix类
在Eigen中,所有矩阵和向量都是Matrix模板类的对象。向量只是行数或者列数为1的特殊矩阵。
1063 1
|
存储 并行计算 算法
[Eigen中文文档] 概述(总目录)
Eigen是基于线性代数的C ++模板库,主要用于矩阵,向量,数值求解器和相关算法。常用的Ceres、G2O等项目均是基于Eigen库。 本系列文章将通过官方文档带你了解Eigen。
3347 1