Eigen:获取稀疏矩阵的核
Eigen: Obtain the kernel of a sparse matrix
给定一个稀疏矩阵 A
和一个向量 b
,我想获得方程 A * x = b
的解 x
以及 A
.
一种可能性是 convert A
到密集表示。
#include <iostream>
#include <Eigen/Dense>
#include <Eigen/SparseQR>
int main()
{
// This is a toy problem. My actual matrix
// is of course bigger and sparser.
Eigen::SparseMatrix<double> A(2,2);
A.insert(0,0) = 1;
A.insert(0,1) = 2;
A.insert(1,0) = 4;
A.insert(1,1) = 8;
A.makeCompressed();
Eigen::Vector2d b;
b << 3, 12;
Eigen::SparseQR<Eigen::SparseMatrix<double>,
Eigen::COLAMDOrdering<int> > solver;
solver.compute(A);
std::cout << "Solution:\n" << solver.solve(b) << std::endl;
Eigen::Matrix2d A_dense(A);
std::cout << "Kernel:\n" << A_dense.fullPivLu().kernel() << std::endl;
return 0;
}
是否可以直接在稀疏表示中做同样的事情?除了 FullPivLu.
之外,我在任何地方都找不到函数 kernel()
我认为@chtz 的回答几乎是正确的,除了我们需要获取最后的 A.cols() - qr.rank() 列。这是一个数学推导。
假设我们对矩阵 Aᵀ 进行 QR 分解为
Aᵀ * P = [Q₁ Q₂] * [R; 0] = Q₁ * R
其中 P 是置换矩阵,因此
Aᵀ = Q₁ * R * P⁻¹.
我们可以看到Range(Aᵀ) = Range(Q₁ * R * P⁻¹) = Range(Q₁)(因为P和R都是可逆的)。
由于 Aᵀ 和 Q₁ 具有相同的范围 space,这意味着 A 和 Q₁ᵀ 也将具有相同的空值 space,即 Null(A) = Null(Q₁ᵀ)。 (这里我们使用 属性 表示 Range(M) 和 Null(Mᵀ) 对于任何矩阵 M
互为补充,因此 Null(A) = complement(Range(Aᵀ)) = complement(范围(Q₁)) = Null(Q₁ᵀ)).
另一方面,由于矩阵[Q₁ Q₂]是正交矩阵,Null(Q₁ᵀ) = Range(Q₂),因此Null(A) = Range(Q₂),即kernal(A) = Q₂。
由于 Q2 是正确的 A.cols() - qr.rank() 列,您可以调用 rightCols(A.cols() - qr.rank())
来检索 A.
的内核
关于内核的更多信息space,您可以参考https://en.wikipedia.org/wiki/Kernel_(linear_algebra)
给定一个稀疏矩阵 A
和一个向量 b
,我想获得方程 A * x = b
的解 x
以及 A
.
一种可能性是 convert A
到密集表示。
#include <iostream>
#include <Eigen/Dense>
#include <Eigen/SparseQR>
int main()
{
// This is a toy problem. My actual matrix
// is of course bigger and sparser.
Eigen::SparseMatrix<double> A(2,2);
A.insert(0,0) = 1;
A.insert(0,1) = 2;
A.insert(1,0) = 4;
A.insert(1,1) = 8;
A.makeCompressed();
Eigen::Vector2d b;
b << 3, 12;
Eigen::SparseQR<Eigen::SparseMatrix<double>,
Eigen::COLAMDOrdering<int> > solver;
solver.compute(A);
std::cout << "Solution:\n" << solver.solve(b) << std::endl;
Eigen::Matrix2d A_dense(A);
std::cout << "Kernel:\n" << A_dense.fullPivLu().kernel() << std::endl;
return 0;
}
是否可以直接在稀疏表示中做同样的事情?除了 FullPivLu.
之外,我在任何地方都找不到函数kernel()
我认为@chtz 的回答几乎是正确的,除了我们需要获取最后的 A.cols() - qr.rank() 列。这是一个数学推导。
假设我们对矩阵 Aᵀ 进行 QR 分解为
Aᵀ * P = [Q₁ Q₂] * [R; 0] = Q₁ * R
其中 P 是置换矩阵,因此
Aᵀ = Q₁ * R * P⁻¹.
我们可以看到Range(Aᵀ) = Range(Q₁ * R * P⁻¹) = Range(Q₁)(因为P和R都是可逆的)。
由于 Aᵀ 和 Q₁ 具有相同的范围 space,这意味着 A 和 Q₁ᵀ 也将具有相同的空值 space,即 Null(A) = Null(Q₁ᵀ)。 (这里我们使用 属性 表示 Range(M) 和 Null(Mᵀ) 对于任何矩阵 M
互为补充,因此 Null(A) = complement(Range(Aᵀ)) = complement(范围(Q₁)) = Null(Q₁ᵀ)).
另一方面,由于矩阵[Q₁ Q₂]是正交矩阵,Null(Q₁ᵀ) = Range(Q₂),因此Null(A) = Range(Q₂),即kernal(A) = Q₂。
由于 Q2 是正确的 A.cols() - qr.rank() 列,您可以调用 rightCols(A.cols() - qr.rank())
来检索 A.
关于内核的更多信息space,您可以参考https://en.wikipedia.org/wiki/Kernel_(linear_algebra)