如何在Eigen中实现零扩展向量包装器并适配MatrixBase接口
实现兼容SparseLU的零扩展向量
要让自定义零扩展向量被Eigen的SparseLU求解器接受,必须让它适配Eigen的表达式模板体系——正确继承Eigen::MatrixBase并实现核心接口。以下是修正后的完整实现方案:
核心实现思路
自定义结构体需继承Eigen::MatrixBase<ZeroExtendedVector<Lhs>>,同时定义Eigen表达式必需的嵌套类型,实现维度查询、系数访问等核心方法,让Eigen能将其识别为合法的矩阵/向量表达式。
完整代码
#include <Eigen/SparseLU> #include <Eigen/Dense> template<typename Lhs> struct ZeroExtendedVector : public Eigen::MatrixBase<ZeroExtendedVector<Lhs>> { // 定义Eigen表达式所需的嵌套类型 using Scalar = typename Lhs::Scalar; using Index = Eigen::Index; using Base = Eigen::MatrixBase<ZeroExtendedVector<Lhs>>; using PlainObject = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>; EIGEN_DEVICE_FUNC ZeroExtendedVector(const Lhs& lhs_, Index numZeros_) : lhs(lhs_), numZeros(numZeros_) {} // 返回扩展后的总维度 EIGEN_DEVICE_FUNC Index rows() const { return lhs.rows() + numZeros; } // 向量列数固定为1 EIGEN_DEVICE_FUNC Index cols() const { return 1; } // 零扩展系数访问逻辑 EIGEN_DEVICE_FUNC Scalar coeff(Index row, Index /*col*/) const { return (row < lhs.rows()) ? lhs.coeff(row, 0) : Scalar(0); } // 可选:实现高效求值逻辑,避免逐个系数调用的开销 template<typename Dest> EIGEN_DEVICE_FUNC void evalTo(Dest& dst) const { dst.resize(rows(), cols()); dst.head(lhs.rows()) = lhs; dst.tail(numZeros).setZero(); } const Lhs& lhs; const Index numZeros; }; // 辅助函数:简化零扩展向量的创建 template<typename Lhs> EIGEN_DEVICE_FUNC ZeroExtendedVector<Lhs> zero_extend(const Lhs& lhs, Eigen::Index numZeros) { return ZeroExtendedVector<Lhs>(lhs, numZeros); } // 使用示例 int main() { // 构建5x5稀疏对角矩阵 Eigen::SparseMatrix<double> A(5,5); A.insert(0,0) = 1; A.insert(1,1) = 2; A.insert(2,2) = 3; A.insert(3,3) = 4; A.insert(4,4) = 5; A.makeCompressed(); // 原始3维向量 Eigen::VectorXd b(3); b << 1, 2, 3; // 零扩展为5维向量 auto b_extended = zero_extend(b, 2); // SparseLU求解线性方程组 Eigen::SparseLU<Eigen::SparseMatrix<double>> solver; solver.compute(A); Eigen::VectorXd x = solver.solve(b_extended); return 0; }
关键说明
- 继承MatrixBase:这是让自定义类型被Eigen识别为合法表达式的核心,MatrixBase会提供大量默认实现,只需补充维度和系数访问方法。
- 嵌套类型定义:
Scalar、Index等类型是Eigen模板推导的基础,必须显式定义。 - coeff方法:实现零扩展的核心逻辑,行索引在原向量范围内返回原系数,超出部分返回0。
- evalTo方法:可选但推荐,提供直接求值到目标矩阵的高效路径,比逐个调用
coeff性能更高。 - 辅助函数:
zero_extend简化实例创建,无需手动指定模板参数。
通过以上实现,ZeroExtendedVector即可直接传入SparseLU::solve方法使用。
内容的提问来源于stack exchange,提问作者Olumide
相关产品推荐
相关产品推荐

