Eigen教程6 - Matrix-free solvers

2023-05-16

博客新址: http://blog.xuezhisd.top
邮箱:xuezhisd@126.com


Matrix-free solvers

像ConjugateGradient 和 BiCGSTAB这样的迭代求解器可以用在 matrix free context。为此,用户必须提供一个继承EigenBase<>的封装类,并实现下面的方法:

  • Index rows() 和 Index cols():分别返回行数和列数。
  • operator* :操作数分别是你自己的类型和一个Eigen密集列向量。

Eigen::internal::traits<> 也必须为封装类型专门定制。

下面的例程,对Eigen::SparseMatrix进行了封装:

// 参考链接:http://eigen.tuxfamily.org/dox/group__MatrixfreeSolverExample.html

#include <iostream>
#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/IterativeLinearSolvers>
#include <unsupported/Eigen/IterativeSolvers>
class MatrixReplacement; //声明类,定义在下面
using Eigen::SparseMatrix;
namespace Eigen {
	namespace internal {
		// MatrixReplacement和SparseMatrix相似,因此继承它的特性
		template<>
		struct traits<MatrixReplacement> :  public Eigen::internal::traits<Eigen::SparseMatrix<double> >
		{};
	}
}
// matrix-free wrapper的简单例子:将用户类型转换成Eigen兼容的类型
// 为了简单,该例子简单封装了Eigen::SparseMatrix
class MatrixReplacement : public Eigen::EigenBase<MatrixReplacement> {
public:
	// Required typedefs, constants, and method:
	typedef double Scalar;
	typedef double RealScalar;
	typedef int StorageIndex;
	enum {
		ColsAtCompileTime = Eigen::Dynamic,
		MaxColsAtCompileTime = Eigen::Dynamic,
		IsRowMajor = false
	};
	Index rows() const { return mp_mat->rows(); }
	Index cols() const { return mp_mat->cols(); }
	template<typename Rhs>
	Eigen::Product<MatrixReplacement,Rhs,Eigen::AliasFreeProduct> operator*(const Eigen::MatrixBase<Rhs>& x) const {
		return Eigen::Product<MatrixReplacement,Rhs,Eigen::AliasFreeProduct>(*this, x.derived());
	}
	// 自定义API:
	MatrixReplacement() : mp_mat(0) {}
	void attachMyMatrix(const SparseMatrix<double> &mat) {
		mp_mat = &mat;
	}
	const SparseMatrix<double> my_matrix() const { return *mp_mat; }
private:
	const SparseMatrix<double> *mp_mat;
};
// Implementation of MatrixReplacement * Eigen::DenseVector though a specialization of internal::generic_product_impl:
namespace Eigen {
	namespace internal {
		template<typename Rhs>
		struct generic_product_impl<MatrixReplacement, Rhs, SparseShape, DenseShape, GemvProduct> // GEMV stands for matrix-vector
			: generic_product_impl_base<MatrixReplacement,Rhs,generic_product_impl<MatrixReplacement,Rhs> >
		{
			typedef typename Product<MatrixReplacement,Rhs>::Scalar Scalar;
			template<typename Dest>
			static void scaleAndAddTo(Dest& dst, const MatrixReplacement& lhs, const Rhs& rhs, const Scalar& alpha)
			{
				// This method should implement "dst += alpha * lhs * rhs" inplace,
				// however, for iterative solvers, alpha is always equal to 1, so let's not bother about it.
				assert(alpha==Scalar(1) && "scaling is not implemented");
				// Here we could simply call dst.noalias() += lhs.my_matrix() * rhs,
				// but let's do something fancier (and less efficient):
				for(Index i=0; i<lhs.cols(); ++i)
					dst += rhs(i) * lhs.my_matrix().col(i);
			}
		};
	}
}
int main()
{
	int n = 10;
	Eigen::SparseMatrix<double> S = Eigen::MatrixXd::Random(n,n).sparseView(0.5,1);
	S = S.transpose()*S; //S'S 对称正定矩阵
	MatrixReplacement A;
	A.attachMyMatrix(S);
	Eigen::VectorXd b(n), x;
	b.setRandom();
	// 使用不同的迭代求解器,来求解 Ax = b with matrix-free version:
	{
		Eigen::ConjugateGradient<MatrixReplacement, Eigen::Lower|Eigen::Upper, Eigen::IdentityPreconditioner> cg;
		cg.compute(A);
		x = cg.solve(b);
		std::cout << "CG:       #iterations: " << cg.iterations() << ", estimated error: " << cg.error() << std::endl;
	}
	{
		Eigen::BiCGSTAB<MatrixReplacement, Eigen::IdentityPreconditioner> bicg;
		bicg.compute(A);
		x = bicg.solve(b);
		std::cout << "BiCGSTAB: #iterations: " << bicg.iterations() << ", estimated error: " << bicg.error() << std::endl;
	}
	{
		Eigen::GMRES<MatrixReplacement, Eigen::IdentityPreconditioner> gmres;
		gmres.compute(A);
		x = gmres.solve(b);
		std::cout << "GMRES:    #iterations: " << gmres.iterations() << ", estimated error: " << gmres.error() << std::endl;
	}
	{
		Eigen::DGMRES<MatrixReplacement, Eigen::IdentityPreconditioner> gmres;
		gmres.compute(A);
		x = gmres.solve(b);
		std::cout << "DGMRES:   #iterations: " << gmres.iterations() << ", estimated error: " << gmres.error() << std::endl;
	}
	{
		Eigen::MINRES<MatrixReplacement, Eigen::Lower|Eigen::Upper, Eigen::IdentityPreconditioner> minres;
		minres.compute(A);
		x = minres.solve(b);
		std::cout << "MINRES:   #iterations: " << minres.iterations() << ", estimated error: " << minres.error() << std::endl;
	}
}

参考

  • http://eigen.tuxfamily.org/dox/group__MatrixfreeSolverExample.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Eigen教程6 - Matrix-free solvers 的相关文章

随机推荐

  • PCL系列——将点云数据写入PCD格式文件

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com PCL系列 PCL系列 读入PCD格式文件操作PCL系列 将点云数据写入PCD格式文件PCL系列 拼接两个点云PCL系列 从深
  • awk one lines

    From http www student northpark edu pemente awk awk1line txt HANDY ONE LINERS FOR AWK 22 July 2003 compiled by Eric Peme
  • PCL系列——拼接两个点云

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com PCL系列 PCL系列 读入PCD格式文件操作PCL系列 将点云数据写入PCD格式文件PCL系列 拼接两个点云PCL系列 从深
  • PCL系列——从深度图像(RangeImage)中提取NARF关键点

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com PCL系列 PCL系列 读入PCD格式文件操作PCL系列 将点云数据写入PCD格式文件PCL系列 拼接两个点云PCL系列 从深
  • PCL系列——如何可视化深度图像

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com PCL系列 PCL系列 读入PCD格式文件操作PCL系列 将点云数据写入PCD格式文件PCL系列 拼接两个点云PCL系列 从深
  • PCL系列——如何使用迭代最近点法(ICP)配准

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com PCL系列 PCL系列 读入PCD格式文件操作PCL系列 将点云数据写入PCD格式文件PCL系列 拼接两个点云PCL系列 从深
  • PCL系列——如何逐渐地配准一对点云

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com PCL系列 PCL系列 读入PCD格式文件操作PCL系列 将点云数据写入PCD格式文件PCL系列 拼接两个点云PCL系列 从深
  • PCL系列——三维重构之泊松重构

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com PCL系列 PCL系列 读入PCD格式文件操作PCL系列 将点云数据写入PCD格式文件PCL系列 拼接两个点云PCL系列 从深
  • PCL系列——三维重构之贪婪三角投影算法

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com PCL系列 PCL系列 读入PCD格式文件操作PCL系列 将点云数据写入PCD格式文件PCL系列 拼接两个点云PCL系列 从深
  • PCL系列——三维重构之移动立方体算法

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com PCL系列 PCL系列 读入PCD格式文件操作PCL系列 将点云数据写入PCD格式文件PCL系列 拼接两个点云PCL系列 从深
  • 解决Ubuntu中文显示为乱码

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 1 安装所需软件 sudo apt get install zh autoconvert sudo apt get insta
  • hexo教程系列——hexo安装教程

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 本文详细描述了如何在Github上 xff0c 使用hexo部署博客 安装Hexo 安装node js node js官方下载
  • Python中类成员函数均为虚函数的理解

    python中类成员函数均为虚函数 我们可以通过下面的函数见识其威力 class A def foo self print 39 a 39 class B A def foo self print 39 b 39 for x in A B
  • MxNet系列——Windows上安装MxNet

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 开发环境 操作系统 xff1a Win7 64bit C 43 43 编译器 xff1a Visual Studio 2010
  • Eigen教程1 - 基础

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 固定大小的矩阵和向量 参考链接 xff1a http eigen tuxfamily org dox 2 0 Tutorial
  • Eigen教程2 - 入门

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 安装Eigen 无需安装 只需将Eigen位置添加到include路径中 Demo 1 MatrixXd xff0c X表示动
  • Eigen教程3 - 稀疏矩阵操作

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 稀疏矩阵操作 操作和求解稀疏问题需要的模块 xff1a SparseCore SparseMatrix 和 SparseVec
  • Eigen教程4 - 稀疏矩阵快速参考指南

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 本文对稀疏矩阵SparseMatrix的主要操作进行了总结 首先 xff0c 建议先阅读 Eigen教程2 稀疏矩阵操作 关于
  • Eigen教程5 - 求解稀疏线性方程组

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com Eigen中有一些求解稀疏系数矩阵的线性方程组 由于稀疏矩阵的特殊的表示方式 xff0c 因此获得较好的性能需要格外注意 查看
  • Eigen教程6 - Matrix-free solvers

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com Matrix free solvers 像ConjugateGradient 和 BiCGSTAB这样的迭代求解器可以用在 m