博客新址: http://blog.xuezhisd.top
邮箱:[email protected]
操作和求解稀疏问题需要的模块:
SparseMatrix是Eigen的稀疏模块的最主要的稀疏矩阵。它实现了Compressed Column (or Row) Storage方案。
SparseMatrix包含了4个精简的数组:
如果中间没有留未占用的空间,就是压缩模式。 对应于Compressed Column (or Row) Storage Schemes (CCS or CRS)。
任何SparseMatrix都可以通过SparseMatrix::makeCompressed()
方法变成稀疏模式。此时,InnerNNZs相对于OuterStarts而言,就是多余的,因为InnerNNZs[j] = OuterStarts[j+1]-OuterStarts[j]。因此SparseMatrix::makeCompressed()
会释放InnerNNZ存储空间。
Eigen的操作总是返回压缩模式的稀疏矩阵。当向一个SparseMatrix插入新元素时,会变成非压缩模式。
SparseVector是SparseMatrix的一个特例,只有 Values 和 InnerIndices数组。没有压缩和非压缩的区别。
$Ax=b$
。// 参考链接:http://eigen.tuxfamily.org/dox/group__TutorialSparse.html
#include
#include
//#include //Qt
#define M_PI 3.14159265358979323846
typedef Eigen::SparseMatrix SpMat; // 声明一个列优先的双精度稀疏矩阵类型
typedef Eigen::Triplet T; //三元组(行,列,值)
void buildProblem(std::vector& coefficients, Eigen::VectorXd& b, int n);
void saveAsBitmap(const Eigen::VectorXd& x, int n, const char* filename);
int main(int argc, char** argv)
{
assert(argc==2);
int n = 300; // 图像的尺寸
int m = n*n; // 未知元素的数量(等于像素数)
// Assembly:
std::vector coefficients; // list of non-zeros coefficients
Eigen::VectorXd b(m); // 等号右边的向量b,根据约束条件生成
buildProblem(coefficients, b, n);
SpMat A(m,m); // 等号左边的矩阵A
A.setFromTriplets(coefficients.begin(), coefficients.end());
// 求解
Eigen::SimplicialCholesky chol(A); // 执行A的 Cholesky分解
Eigen::VectorXd x = chol.solve(b); // 使用A的Cholesky分解来求解等号右边的向量b
// Export the result to a file:
//saveAsBitmap(x, n, argv[1]);
return 0;
}
void insertCoefficient(int id, int i, int j, double w, std::vector& coeffs,
Eigen::VectorXd& b, const Eigen::VectorXd& boundary)
{
int n = int(boundary.size());
int id1 = i+j*n;
if(i==-1 || i==n) b(id) -= w * boundary(j); // constrained coefficient
else if(j==-1 || j==n) b(id) -= w * boundary(i); // constrained coefficient
else coeffs.push_back(T(id,id1,w)); // unknown coefficient
}
void buildProblem(std::vector& coefficients, Eigen::VectorXd& b, int n)
{
b.setZero();
Eigen::ArrayXd boundary = Eigen::ArrayXd::LinSpaced(n, 0,M_PI).sin().pow(2);
for(int j=0; j bits = (x*255).cast();
QImage img(bits.data(), n,n,QImage::Format_Indexed8);
img.setColorCount(256);
for(int i=0;i<256;i++) img.setColor(i,qRgb(i,i,i));
img.save(filename);
}
*/
SparseMatrix > mat(1000,2000); //声明一个 1000x2000 列优先的压缩的稀疏矩阵(元素类型:complex)
SparseMatrix mat(1000,2000); //声明一个 1000x2000 行优先的压缩的稀疏矩阵(元素类型:double)
SparseVector > vec(1000); //声明一个1000维的稀疏的列向量,元素类型为complex
SparseVector vec(1000); //声明一个1000维的稀疏的行向量,元素类型为double
// 参考链接:http://eigen.tuxfamily.org/dox/group__TutorialSparse.html
#include
#include
using namespace std;
using namespace Eigen;
int main(int argc, char** argv)
{
SparseMatrix mat(1000,2000);//创建一个行优先的,维度为1000x2000的稀疏矩阵
SparseVector vec(1000);
//标准维度
cout << "mat.rows() = " << mat.rows() << endl;
cout << "mat.cols() = " << mat.cols() << endl;
cout << "mat.size() = " << mat.size() << endl;
cout << "vec.size() = " << vec.size() << endl;
//内/外维度
cout << "mat.innerSize() = " << mat.innerSize() << endl; //行优先,所以为列数
cout << "mat.outerSize() = " << mat.outerSize() << endl;
//非零元素个数
cout << "mat.nonZeros() = " << mat.nonZeros() << endl;
cout << "vec.nonZeros() = " << vec.nonZeros() << endl;
return 0;
}
// 参考链接:http://eigen.tuxfamily.org/dox/group__TutorialSparse.html
#include
#include
using namespace std;
using namespace Eigen;
int main(int argc, char** argv)
{
SparseMatrix mat(5,7);//创建一个行优先的,维度为1000x2000的稀疏矩阵
//随机访问(读/写)元素
cout << mat.coeffRef(0,0) << endl; //读取元素
mat.coeffRef(0,0) = 5;
cout << mat.coeffRef(0,0) << endl; //写入元素
//迭代访问稀疏矩阵
cout << "\n迭代访问稀疏矩阵的元素:" << endl;
for (int k=0; k::InnerIterator it(mat,k); it; ++it)
{
it.value(); // 元素值
it.row(); // 行标row index
it.col(); // 列标(此处等于k)
it.index(); // 内部索引,此处等于it.row()
}
cout << mat << endl;
//迭代访问稀疏向量
SparseVector vec(5);
//vec.coeffRef(0,0) = 1;
for (SparseVector::InnerIterator it(vec); it; ++it)
{
it.value(); // == vec[ it.index() ]
it.index(); //索引
}
cout << vec << endl;
return 0;
}
// 参考链接:http://eigen.tuxfamily.org/dox/group__TutorialSparse.html
#include
#include
using namespace std;
using namespace Eigen;
typedef Eigen::Triplet T;
typedef Eigen::SparseMatrix SparseMatrixType;
int main(int argc, char** argv)
{
int rows=10, cols = 10;
int estimation_of_entries = 10; //预计非零元素的个数
std::vector tripletList;
tripletList.reserve(estimation_of_entries);
int j = 1; // 列标
for(int i=0; i
// 参考链接:http://eigen.tuxfamily.org/dox/group__TutorialSparse.html
#include
#include
using namespace std;
using namespace Eigen;
int main(int argc, char** argv)
{
int rows=10, cols = 10;
SparseMatrix mat(rows,cols); // 默认列优先
mat.reserve(VectorXi::Constant(cols,6)); //关键:为每一列保留6个非零元素空间
for(int i=0; i<3; i++){ //遍历行
for(int j=0;j<3; j++){
int v_ij = i+j+1;
mat.insert(i,j) = v_ij; // alternative: mat.coeffRef(i,j) += v_ij;
}
}
mat.makeCompressed(); //压缩剩余的空间
//
cout << mat << endl;
return 0;
}
sm1.real()
sm1.imag()
-sm1
0.5*sm1
sm1+sm2
sm1-sm2
sm1.cwiseProduct(sm2)
sm4 = sm1 + sm2 + sm3;
,sm1,sm2,sm3必须都是行优先或列优先的;sm4没有要求。$A^T+A$
时,必须先将前一项生成一个兼容顺序的临时矩阵,然后再计算。如下所示:SparseMatrix A, B;
B = SparseMatrix(A.transpose()) + A
sm2 = sm1.cwiseProduct(dm1);
dm2 = sm1 + dm1;
dm2 = dm1 - sm1;
dm2 = dm1;
dm2 += sm1;
sm1 = sm2.transpose();
sm1 = sm2.adjoint();
dv2 = sm1 * dv1;
dm2 = dm1 * sm1.adjoint();
dm2 = 2. * sm1 * dm1;
dm2 = sm1.selfadjointView<>() * dm1; // 当存储了A的所有元素
dm2 = A.selfadjointView() * dm1; //仅当存储了A的上半部分
dm2 = A.selfadjointView() * dm1; // 仅当存储了A的下半部分
sm3 = sm1 * sm2;
sm3 = 4 * sm1.adjoint() * sm2;
sm3 = (sm1 * sm2).pruned(); // 去除数值零
sm3 = (sm1 * sm2).pruned(ref); // 去除比ref小的元素
sm3 = (sm1 * sm2).pruned(ref,epsilon); // 去除比ref*epsilon小的元素
PermutationMatrix P = ...;
sm2 = P * sm1;
sm2 = sm1 * P.inverse();
sm2 = sm1.transpose() * P;
SparseMatrix sm1;
sm1.col(j) = ...;
sm1.leftCols(ncols) = ...;
sm1.middleCols(j,ncols) = ...;
sm1.rightCols(ncols) = ...;
SparseMatrix sm2;
sm2.row(i) = ...;
sm2.topRows(nrows) = ...;
sm2.middleRows(i,nrows) = ...;
sm2.bottomRows(nrows) = ...;
dm2 = sm1.triangularView(dm1);
dv2 = sm1.transpose().triangularView(dv1);
dm2 = sm1.selfadjointView<>() * dm1; // 当存储了A的所有元素
dm2 = A.selfadjointView() * dm1; //仅当存储了A的上半部分
dm2 = A.selfadjointView() * dm1; // 仅当存储了A的下半部分
sm2 = sm1.selfadjointView(); // 从上三角部分生成一个全的伴随矩阵
sm2.selfadjointView() = sm1.selfadjointView(); // 复制上三角部分到下三角部分
PermutationMatrix P = ...;
sm2 = A.selfadjointView().twistedBy(P); // 从A的上三角部分计算 P S P',生成一个全矩阵
sm2.selfadjointView() = A.selfadjointView().twistedBy(P); // compute P S P' from the lower triangular part of A, and then only compute the lower part