Eigen矩阵运算库快速上手

2023-11-10

目录

1. 配置

2. 初始化

2.1 Array类

2.2 Vector类

2.3 Matrix类

2.4 Vector赋值

2.5 高级初始化

3. 矩阵计算

3.1 矩阵基本计算

3.2 线性求解

3.3 特征值计算

3.4 奇异值分解

总结

做科研类项目,尤其是与线性优化,主成分分析有关的项目,势必需要用到矩阵计算及相关的优化工具。很多同学会利用matlab完成项目需求,这当然是一个不错的选择。但是,对于平台有一定要求的项目,尤其是那些基于C++开发的工程项目,使用matlab就会带来一些不便。我们希望有方便的矩阵开源工具,可以集成在项目中,以简化程序部署与使用的难度。这里就不得不提到大名鼎鼎的矩阵开源库,Eigen。今天这篇博客,就来跟大家介绍下Eigen部署与使用的基本知识,方便新手朋友能够快速掌握基于Eigen实现的矩阵计算与优化功能。


1. 配置

首先我们在官网上下载Eigen最新版本(V3.4)

3.4.0 · libeigen / eigen · GitLab

这里我们使用VS2022作为开发平台。配置非常简单,只要在VC++目录的include添加Eigen路径就可以。

 这里贴一段测试代码:

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
typedef Eigen::Matrix<int, 3, 3> Matrix3i;

int main()
{	
    Matrix3i m1;
    m1 << 1, 2, 3, 4, 5, 6, 7, 8, 9;
    cout << "m1 = \n" << m1 << endl;
    Matrix3i m2;
    m2 << 2, 0, 0, 0, 2, 0, 0, 0, 2;
    cout << "m2 = \n" << m2 << endl;
    cout << "m1 * m2 = \n" << (m1 * m2) << endl;
    return 0;
}

打印结果:


2. 初始化

在配置完Eigen后,接下来我们希望知道如何对向量和矩阵实现初始化。Eigen支持初始化方式很多, 参考博客Eigen库的使用小结Eigen库的使用Eigen初始化,我们列出几种供参考:

2.1 Array类

直接赋值

Eigen::Array<int, 3, 1> arr_1(1, 2, 3);

流输入赋值

Eigen::Array<int, 3, 3> arr_2;
    arr_2 <<
        1, 2, 3,
        4, 5, 6,
        7, 8, 9;

指针方式赋值

std::vector<int> vec_int{ 1,2,3,4,5,6,7,8,9 };
    Eigen::Array<int, 3, 3> arr_3(vec_int.data());

2.2 Vector类

Vector的赋值方法与Array基本相同。Vector可以被看做是一种特殊的Matrix。

Eigen::Vector3f v1 = Eigen::Vector3f::Zero();

Eigen::Vector3d v2(1.0, 2.0, 3.0);

Eigen::VectorXf v3(20); //维度为20的向量,未初始化.
v3 << 1.0 , 2.0 , 3.0;

2.3 Matrix类

与Array的初始化方法基本相同

Eigen::Matrix<double,2,2> m;
m << 1,2,3,4;

Eigen::MatrixXf m1(2,3);
m1 << 1,2,3,
	  4,5,6;

Eigen::Matrix3d m2 = Eigen::Matrix3d::Identity();//Eigen::Matrix3d::Zero();

Eigen::Matrix3d m3 = Eigen::Matrix3d::Random(); //随机初始化

2.4 Vector赋值

有的时候,我们会将数据存储在C++的数据结构vector中。此时,我们希望将vector的数据转换为矩阵,并进行相应计算。除了使用指针方式,我们还可以直接将vector的数据拷贝到矩阵中。

std::vector<std::vector<double>> LX;
MatrixXd m_Lx(LX.size(), 3);	
for (int i = 0; i < LX.size(); i++) {
	m_Lx(i, 0) = LX[i][0];
	m_Lx(i, 1) = LX[i][1];
	m_Lx(i, 2) = LX[i][2];
}

假设LX是一个点云数据,每一个点是一个三维向量。对应建立的MatrixXd m_LX即与LX具有相同的维度,即将C++的vector转换为eigen的matrix。

2.5 高级初始化

参考matlab,eigen也提供了一些功能丰富的高级数据初始化方法,包括对行列向量的独立赋值,块赋值等。这里我们列出一些示例代码,供参考。

列向量赋值

RowVectorXd rv1(1,2,3);

块赋值

对m4进行计算,并按块赋值给m5,输出m5: 

MatrixXf m4(2,2);
m4 << 1,2,3,4;
MatrixXf m5(4,4);
m5 << m4, m4 / 10, m4 * 10, m4;//将m5分了四块赋值

更加精准的赋值,首先输入第一行: 1, 2, 3; 之后按照block的信息,在矩阵的第二行,第一列插入一个2*2的子矩阵,4, 5, 6, 7;最后,在第三列,最后两个位置tail(2), 插入6, 9。可以看到,上述操作实现了对一个矩阵分块精准赋值。

Matrix3f m;
m.row(0) << 1,2,3;
m.block(1,0,2,2) << 4,5,6,7; 
m.col(2).tail(2) << 6,9;

3. 矩阵计算

基于赋值后的矩阵,我们希望通过Eigen实现对矩阵的计算。这里我们将矩阵计算分为三部分,包括矩阵基本计算,线性求解,特征值计算以及奇异值分解。

3.1 矩阵基本计算

矩阵基本计算比较简单,包括加,减,叉乘,点乘,转置,求逆等。

MatrixXf m = MatrixXf::Random(3,3);
MatrixXf m2 = MatrixXf::Random(3,3);
m.row(i);//矩阵第i行
m.col(j);//矩阵第j列
m.transpose();//转置
m.conjugate();//共轭
m.adjoint(); //共轭转置
m.minCoeff();//所有元素中最小元素
m.maxCoeff();//所有元素中最大元素
m.trace();//迹,对角元素的和
m.sum(); //所有元素求和
m.prod(); //所有元素求积
m.mean(); //所有元素求平均
m.dot(m2); //点乘
m.cross(m2);//叉乘

3.2 线性求解

求解Ax=b,eigen提供了几个工具,包括:

 一般大家会选择LLT和LDLT

 Eigen::Matrix2f A, b;
 A << 2, -1, -1, 3;
 b << 1, 2, 3, 1;
 std::cout << "Here is the matrix A:\n" << A << std::endl;
 std::cout << "Here is the right hand side b:\n" << b << std::endl;
 Eigen::Matrix2f x = A.ldlt().solve(b);//or A.llt().solve(B);                   
 std::cout << "The solution is:\n" << x << std::endl;

3.3 特征值计算

特征值及对应的特征向量计算,在矩阵分析中占有重要位置。基于Eigen的特征值计算如下:

Eigen::MatrixXd m = Eigen::MatrixXd::Random(3,3);
Eigen::MatrixXd mTm = m.transpose() * m;//构成中心对其的协方差矩阵

//计算
Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eigen_solver(mTm);

//取出特征值和特征向量
Eigen::VectorXd eigenvalues = eigen_solver.eigenvalues();
Eigen::MatrixXd eigenvectors = eigen_solver.eigenvectors();

Eigen::VectorXd v0 = eigenvectors.col(0);// 因为特征值一般按从小到大排列,所以col(0)就是最小特征值对应的特征向量

3.4 奇异值分解

参考博客:矩阵奇异值分解简介

奇异值分解(singular value decomposition, SVD):将矩阵分解为奇异向量(singular vector)和奇异值(singular value)。通过奇异值分解,我们会得到一些与特征分解相同类型的信息。然而,奇异值分解有更广泛的应用。每个实数矩阵都有一个奇异值分解,但不一定都有特征分解。例如,非方阵的矩阵没有特征分解,这是我们只能使用奇异值分解。

将矩阵A分解成三个矩阵的乘积:A=UDV^T。

这些矩阵中的每一个经定义后都拥有特殊的结构。矩阵U和V都被定义为正交矩阵,而矩阵D被定义为对角矩阵。注意,矩阵D不一定是方阵。对角矩阵D对角线上的元素被称为矩阵A的奇异值(singular value)。矩阵U的列向量被称为左奇异向量(left singular vector),矩阵V的列向量被称为右奇异向量(right singular vector)。A的左奇异向量是AA^T的特征向量。A的右奇异向量是A^TA的特征向量。A的非零奇异值是A^TA特征值的平方根,同时也是AA^T特征值的平方根。

JacobiSVD<MatrixXd> svd(J, ComputeThinU | ComputeThinV);
U = svd.matrixU();
V = svd.matrixV();
D_t = svd.singularValues();

总结

作为基于C++的矩阵运算库,Eigen部署简单,执行效率高,集成了功能丰富的矩阵运算函数。掌握Eigen,能够显著提高项目对矩阵优化问题的求解效率。

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

Eigen矩阵运算库快速上手 的相关文章

随机推荐

  • Data collection (imaging)

    Now that we ve talked about sample prep let s talk about imaging 0 05 In a single particle project the images can either
  • LeetCode左程云算法课笔记

    左程云算法课笔记 剑指Offer 位运算 运算符理解 寻找出现双中的单数 取出一个数最右边1的位置 找所有双出现中的两个单数 整数二进制奇数位偶数位交换 数组中全部出现k次返回出现一次的数 链表 判读链表元素是否回文 利用栈结构 利用栈结构
  • 解决VS打不开xxx.ui文件,xxx.ui无法打开文件

    目录 场景复现 解决方案 场景复现 在使用vs进行开发时 居然无法打开qt的ui文件 这本质上是因为找不到designer exe的路径 解决方案 1 右击ui文件 然后选择打开方式 2 点击右侧的添加按钮 3 点击程序后面的 按钮选择合适
  • PCIe专题学习——4.0(物理层结构解析)

    之前我们讲了对PCIe的一些基础概念作了一个宏观的介绍 了解了PCIe是一种封装分层协议 packet based layered protocol 主要包括事务层 Transaction layer 数据链路层 Data link lay
  • Java相关注解

    标题 TableField Mybatis plus使用注解 TableField exist false 注明非数据库字段属性 TableField exist false 注解加载bean属性上 表示当前属性不是数据库字段 但项目中必须
  • vue3 父子组件传参详解

    前言 我引用了大佬的文章 但我实在找不到网址链接了 我记录在笔记上的 如果大佬看见了 麻烦给我说一下 我注明一下出处 建议先看son vue 里面写了那三种方式 首先放一个我的demo defineProps什么的父子传参api不用引入 直
  • 06 科技英语|控制与优化学科词汇

    maneuver n 策略 v 操控 调遣 manipulate vt 熟练控制 scalability n 可扩展性 leverage n 杠杆 v 促使 改变 flexibility n 弹性 dispatch n 急件 v 调度 派遣
  • extern关键字的用法知识点总结

    extern关键字的用法 编译C文件的步骤 数据类型及其长度 知识点总结 一 extern关键字的用法 extern关键字可以用来声明变量 函数作为外部变量或者函数供其它文件使用 extern表明变量或者函数是定义在其他其他文件中的 例如
  • 《Python编程:从入门到实践》第九章练习题

    Python编程 从入门到实践 第九章练习题 Python编程 从入门到实践 第九章练习题 9 1 餐馆 9 2 三家餐馆 9 3 用户 9 4 就餐人数 9 5 尝试登录次数 9 6 冰淇淋小店 9 7 管理员 9 8 权限 9 9 电瓶
  • python+selenium+PhantomJS爬取唯品会

    由于唯品会是利用js动态生成html作为反爬机制 所以不能用以前的爬取html的方法进行爬取 本程序是用selenium PhantomJS对唯品会进行爬取 可以根据需要输入要爬取的商品 还有爬取的起始页和结束页 程序代码以及注释的内容如下
  • vue[el-table]表格内附件上传、elementui 的http-request 上传附件,并且还可以传参数

    解决 通过http request
  • cmd 窗口 make clean process_begin: CreateProcess(NULL, rm Dynamics.o test.o, …) failed.

    CMD执行make clean报错 make clean rm Dynamics o test o process begin CreateProcess NULL rm Dynamics o test o failed make e 2
  • layui 弹出iframe选择数据并获取数据

    var layer layui layer layer open type 2 2表示弹出的是iframe 1表示弹出的是层 offset auto title 选择题目 font size 18px area 500px 300px sc
  • 华为HCIE云计算之IPsan存储裸设备映射给Linux主机

    华为HCIE云计算之IPsan存储裸设备映射给Linux主机 一 环境简介 1 Linux系统版本 2 各服务器IP地址 二 配置数据存储 1 登录华为V3数据存储 2 创建LUN 3 创建Lun组 4 创建主机 5 创建主机组 6 创建主
  • 行业轮动策略(思想+源码)

    一 行业轮动策略简介 行业轮动是利用市场趋势获利的一种主动量化投资交易策略 其本质是利用不同投资品种强势时间的错位对行业品种进行切换以达到投资收益最大化的目的 通俗点讲就是根据不同行业的区间表现差异 性进行轮动配置 力求能够抓住区间内表现较
  • yarn add报错error: Missing list of packages to add to your project.

    问题描述 运行yarn add命令安装全部依赖项报错 原因 yarn安装全部依赖是 yarn 或者 yarn install 不是yarn add这个命令 yarn add 后面需要跟具体的包名安装某个包 解决 更换成 yarn 或者 ya
  • DDR3详解(以Micron MT41J128M8 1Gb DDR3 SDRAM为例)之一

    1 结构框图 2 管脚功能描述 管脚符号 类型 描述 A0 A9 A10 AP A11 A12 BC A13 Input 地址输入 为ACTIVATE命令提供行地址 和为READ WRITE命令的列地址和自动预充电位 A10 以便从某个ba
  • 基于Selenium模块实现无界面模式 & 执行JS脚本

    此篇文章主要介绍如何使用 Selenium 模块实现 无界面模式 执行JS脚本 把滚动条拉到底部 并以具体的示例进行展示 1 Selenium 设置无界面模式 创建浏览器对象之前 创建 options 功能对象 options webdri
  • Qt 自动单元测试Auto Test Project详解

    Qt 自动单元测试Auto Test Project详解 有时 残缺也是一种美 测试 则意味着需要投入 有些项目的迭代周期很短 如果也搞一个 test 则可能性价比很低 Qt 自动单元测试Auto Test Project详解 官方 htt
  • Eigen矩阵运算库快速上手

    目录 1 配置 2 初始化 2 1 Array类 2 2 Vector类 2 3 Matrix类 2 4 Vector赋值 2 5 高级初始化 3 矩阵计算 3 1 矩阵基本计算 3 2 线性求解 3 3 特征值计算 3 4 奇异值分解 总