使用特征值求解线性方程组
Solving Systems of Linear Equations using Eigen
我目前正在使用 C++ 进行流体模拟,该算法的一部分是求解稀疏线性方程组。人们建议为此使用库 Eigen。我决定使用我编写的这个短程序对其进行测试:
#include <Eigen/SparseCholesky>
#include <vector>
#include <iostream>
int main() {
std::vector<Eigen::Triplet<double>> triplets;
triplets.push_back(Eigen::Triplet<double>(0, 0, 1));
triplets.push_back(Eigen::Triplet<double>(0, 1, -2));
triplets.push_back(Eigen::Triplet<double>(1, 0, 3));
triplets.push_back(Eigen::Triplet<double>(1, 1, -2));
Eigen::SparseMatrix<double> A(2, 2);
A.setFromTriplets(triplets.begin(), triplets.end());
Eigen::VectorXd b(2);
b[0] = -2;
b[1] = 2;
Eigen::SimplicialCholesky<Eigen::SparseMatrix<double>> chol(A);
Eigen::VectorXd x = chol.solve(b);
std::cout << x[0] << ' ' << x[1] << std::endl;
system("pause");
}
它给出了这两个等式:
x - 2y = -2
3x - 2y = 2
正确的解法是:
x = 2
y = 2
但问题是程序运行时,输出:
0.181818 -0.727273
这是完全错误的!我已经调试了几个小时,但它是一个非常短的程序,我完全按照 Eigen 网站上的教程进行操作。有人知道是什么导致了这个问题吗?
P.S。我知道我使用的 类 用于稀疏矩阵,但它们与普通矩阵 类 的唯一区别是元素的存储方式。
SimplicialCholesky
用于对称正定 (SPD) 矩阵,您组装的矩阵甚至不对称。默认情况下它只读取下三角部分的条目而忽略其他部分,所以它解决了:
x + 3y = -2
3x -2y = 2
如您所见,对于非对称平方问题,您需要在迭代求解器的世界中使用基于 LU 或 BICGSTAB
的直接求解器。 doc.
中总结了所有这些
您应该使用能够处理非对称稀疏矩阵的求解器。另一种可能的方法是寻求不是原始系统 [A]x=b 而是 [A]T*[A]x=[A]T*b 的解决方案,其中 [A]T 代表 [A] 转置.后一个系统的矩阵是对称且正定的(只要 [A] 是非奇异的)。唯一的缺点是 [A]T[A] 如果原来的 [A] 在这个意义上不是 "good",则可能相当病态。只是旨在解决此类问题的软件示例:
http://members.ozemail.com.au/~comecau/CMA_LS_Sparse.htm
我目前正在使用 C++ 进行流体模拟,该算法的一部分是求解稀疏线性方程组。人们建议为此使用库 Eigen。我决定使用我编写的这个短程序对其进行测试:
#include <Eigen/SparseCholesky>
#include <vector>
#include <iostream>
int main() {
std::vector<Eigen::Triplet<double>> triplets;
triplets.push_back(Eigen::Triplet<double>(0, 0, 1));
triplets.push_back(Eigen::Triplet<double>(0, 1, -2));
triplets.push_back(Eigen::Triplet<double>(1, 0, 3));
triplets.push_back(Eigen::Triplet<double>(1, 1, -2));
Eigen::SparseMatrix<double> A(2, 2);
A.setFromTriplets(triplets.begin(), triplets.end());
Eigen::VectorXd b(2);
b[0] = -2;
b[1] = 2;
Eigen::SimplicialCholesky<Eigen::SparseMatrix<double>> chol(A);
Eigen::VectorXd x = chol.solve(b);
std::cout << x[0] << ' ' << x[1] << std::endl;
system("pause");
}
它给出了这两个等式:
x - 2y = -2
3x - 2y = 2
正确的解法是:
x = 2
y = 2
但问题是程序运行时,输出: 0.181818 -0.727273
这是完全错误的!我已经调试了几个小时,但它是一个非常短的程序,我完全按照 Eigen 网站上的教程进行操作。有人知道是什么导致了这个问题吗?
P.S。我知道我使用的 类 用于稀疏矩阵,但它们与普通矩阵 类 的唯一区别是元素的存储方式。
SimplicialCholesky
用于对称正定 (SPD) 矩阵,您组装的矩阵甚至不对称。默认情况下它只读取下三角部分的条目而忽略其他部分,所以它解决了:
x + 3y = -2
3x -2y = 2
如您所见,对于非对称平方问题,您需要在迭代求解器的世界中使用基于 LU 或 BICGSTAB
的直接求解器。 doc.
您应该使用能够处理非对称稀疏矩阵的求解器。另一种可能的方法是寻求不是原始系统 [A]x=b 而是 [A]T*[A]x=[A]T*b 的解决方案,其中 [A]T 代表 [A] 转置.后一个系统的矩阵是对称且正定的(只要 [A] 是非奇异的)。唯一的缺点是 [A]T[A] 如果原来的 [A] 在这个意义上不是 "good",则可能相当病态。只是旨在解决此类问题的软件示例: http://members.ozemail.com.au/~comecau/CMA_LS_Sparse.htm