目录
1)行、列、大小可以通过rows()、cols()、size()获取
4)所有元素的和,积,最大值,最小值,迹sum())、prod(),、maxCoeff()、minCoeff()、trace()
一、Dev c++安装eigen环境
- 打开Dev c++编译器
- 点击Tools-Package Manager
- 点击左上角Install, 文件类型选择所有,选择压缩包
- 弹出窗口后点击Install即可,安装完毕后的包即在菜单中显示
- 点击Tools(工具)-compiler options(编译选项)-directories(目录)-C++ includes(C++包含文件)-右下角文件选项添加库地址
- 添加头文件成功后,点击🆗
- 新建source file,并保存
- 测试
#include <iostream>
#include <Eigen/Dense>
using Eigen::MatrixXd;
int main()
{
MatrixXd m(2,2);
m(0,0) = 3;
m(1,0) = 2.5;
m(0,1) = -1;
m(1,1) = m(1,0) + m(0,1);
std::cout << m << std::endl;
}
二、Eigen库
Eigen库被分为一个Core模块和其他一些模块,每个模块有一些相应的头文件。 为了便于引用,Dense模块整合了一系列模块;Eigen模块整合了所有模块。一般情况下,include<Eigen/Dense>
就够了。
1.Matrix类(Matrix<类型, 行, 列>):
所有矩阵或者向量都是Matrix这个模板类产生的对象。
Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>
其中:
- Scalar:表示元素的类型;
- RowsAtCompileTime:矩阵的行;
- ColsAtCompileTime:矩阵的列。
Matrix<typename Scalar,
int RowsAtCompileTime,
int ColsAtCompileTime,
int Options = 0,
int MaxRowsAtCompileTime = RowsAtCompileTime,
int MaxColsAtCompileTime = ColsAtCompileTime>
- Options:一个比特位,默认是按列存储,如果使用按行存储:
Matrix<float, 3, 3, RowMajor>
- MaxRowsAtCompileTime和MaxColsAtCompileTime:表示在编译阶段矩阵的上限。主要是避免动态内存分配
Matrix<float, Dynamic, Dynamic, 0, 3, 4>
在库中,用typdef为我们定义了一些常用的矩阵,例如:
typedef Matrix<float, 4, 4> Matrix4f;
当然我们也可以自己设置,矩阵的行和列可以设置为固定的值也可以设置动态的(Dynamic),小的尺寸用固定的,大的尺寸用动态的,使用固定尺寸可以避免动态内存的开辟。
typedef Matrix<double, Dynamic, Dynamic> MatrixXd;
默认的构造函数不执行任何空间分配,也不初始化矩阵的元素。
Matrix3f a;
MatrixXf b;
指定大小的矩阵,只是分配相应大小的空间,未初始化元素。
MatrixXf a(10,15);
VectorXf b(30);
为了对固定大小和动态大小的矩阵提供统一的API,对指定大小的Matrix传递sizes也是合法的(传递也被忽略)。
Matrix3f a(3,3);
可以用构造函数提供4以内尺寸的vector的初始化。
Vector2d a(5.0, 6.0);
Vector3d b(5.0, 6.0, 7.0);
Vector4d c(5.0, 6.0, 7.0, 8.0);
2.Vector类(向量)
列向量:
typedef Matrix<float, 3, 1> Vector3f;
行向量:
typedef Matrix<int, 1, 2> RowVector2i
3.初始化方式
1)通过括号进行赋值
- 矩阵索引赋值:
MatrixXd m1(2,2);
m1(0,0) = 3;
m1(1,0) = 2.5;
m1(0,1) = -1;
m1(1,1) = m1(1,0) + m1(0,1);
- 向量索引:
Eigen::VectorXd v(2);
v[0]=1;
v[1]=2;
或
Eigen::VectorXd v(2);
v(0)=1;
v(1)=2;
注意:
- 矩阵索引只能用(),因为C++操作符重载[]只能接收一个参数,而矩阵的行和列需要两个参数。
- []可以用在向量的索引,因为向量的索引是一维的。
2)通过逗号初始化
Matrix3f m;
m << 1, 2, 3,
4, 5, 6,
7, 8, 9;
std::cout << m;
4.矩阵的属性
1)行、列、大小可以通过rows()、cols()、size()获取
std::cout<<"行:"<<m.rows()<<std::endl;
std::cout<<"列:"<<m.cols()<<std::endl;
std::cout<<"大小:"<<m.size()<<std::endl;
可以指定输出某行或列的数据。
Operation | Method |
---|---|
ith row | matrix.row(i) |
jth colum | matrix.col(j) |
std::cout<<"第一行: "<<std::endl<<m.row(0)<<std::endl;
2)resize()
m.resize(2,3);
cout<<m<<endl;
cout<<"行: "<<m.cols()<<" 列: "<<m.rows()<<" 大小: "<<m.size()<<endl;
注意:
- 只有行和列是动态参数的时候才可以使用,否则会报错,而且输入的时候编译器会检查;
- 如果matrix的实际大小不改变,resize函数不做任何操作。resize操作会执行析构函数,元素的值会被改变,如果不想改变执行 conservativeResize()
3)复制(操作符=)
将一个矩阵复制到另外一个。Eigen会自动resize左变量大小等于右变量大小,比如:
#include<iostream>
#include<Eigen/Dense>
int main(){
Eigen::MatrixXi m(2,3);
std::cout<<"m'size: "<<m.rows()<<"x"<<m.cols()<<std::endl;
Eigen::MatrixXi n(5,3);
m=n;
std::cout<<"m'size: "<<m.rows()<<"x"<<m.cols()<<std::endl;
return 0;
}
5.矩阵的操作
1)矩阵的+、-、数×、乘法
左右两侧变量具有相同的尺寸(行和列),并且元素类型相同(Eigen不自动转化类型),其运算和int,float等基本类型相同。
- 二元运算 + 如a+b
- 二元运算 - 如a-b
- 一元运算 - 如-a
- 复合运算 += 如a+=b
- 复合运算 -= 如a-=b
- 二元运算 * 如matrix*scalar
- 二元运算 * 如scalar*matrix
- 二元运算 / 如matrix/scalar
- 复合运算 *= 如matrix*=scalar
- 复合运算 /= 如matrix/=scalar
#include<iostream>
#include<Eigen/Dense>
using namespace std;
int main()
{
Eigen::Matrix2i m;
m<<1,0,2,0;
Eigen::Matrix<int,2,3> n;
n(0,0)=1;
n(0,1)=2;
n(0,2)=3;
n(1,0)=1;
n(1,1)=2;
n(1,2)=3;
std::cout<<"m: "<<std::endl<<m<<std::endl;
std::cout<<"n: "<<std::endl<<n<<std::endl;
/*
*乘法
*/
Eigen::MatrixXi M;
M=m*n;
std::cout<<"M: "<<std::endl<<M<<std::endl;
/*
*加法
*/
Eigen::MatrixXi N;
N=M+n;
std::cout<<"N: "<<std::endl<<N<<std::endl;
/*
*数乘
*/
Eigen::MatrixXi L;
L=M*3;
std::cout<<"L: "<<std::endl<<L<<std::endl;
return 0;
}
2)点×和叉×
- 点乘:dot();
- 叉乘:cross();
Eigen::Vector3d v(3,4,5);
Eigen::Vector3d w(0,2,3);
cout<<"dot: "<<v.dot(w)<<endl;
cout<<"cross: "<<std::endl<<v.cross(w)<<endl;
3)转置、共轭、伴随
- 表示transpose(转置)
- 表示conjugate(共轭)
- 表示adjoint(共轭转置/ 伴随矩阵)
/*
*转置、共轭、伴随
*/
Eigen::MatrixXd a=Eigen::MatrixXd::Random(2,2);
cout<<"a: "<<std::endl<<a<<endl;
cout<<"转置: "<<std::endl<<a.transpose()<<endl;
cout<<"共轭: "<<std::endl<<a.conjugate()<<endl;
cout<<"伴随: "<<std::endl<<a.adjoint()<<endl;
注意:
- transpose和adjoint会简单的返回一个代理对象并不对本身做转置。
- 如果执行
b=a.transpose()
,a不变,转置结果被赋值给b。- 如果执行
a=a.transpose()
Eigen在转置结束之前结果会开始写入a,所以a的最终结果不一定等于a的转置。- 对
a=a.transpose()
这种操作,如果要就地转置可以使用a.transposeInPlace();(别名问题)
Matrix2i a; a << 1, 2, 3, 4;
cout << "Here is the matrix a:\n" << a << endl;
a = a.transpose(); // !!! do NOT do this !!!
cout << "and the result of the aliasing effect:\n" << a << endl;
Here is the matrix a:
1 2
3 4
and the result of the aliasing effect:
1 2
2 4
4)所有元素的和,积,最大值,最小值,迹
- 和:sum();
- 积:prod();
- 最大值:maxCoeff();
- 最小值:minCoeff();
- 迹:trace();
#include <Eigen/Core>
#include<Eigen/Dense>
#include<iostream>
using namespace std;
using namespace Eigen;
int main()
{
Matrix2d m(2,2);
m(0,0)=-1;
m(0,1)=2;
m(1,0)=3;
m(1,1)=1;
Vector2d v1(1,2),v2(2,3);
cout<<m.sum()<<endl;
cout<<m.prod()<<endl;
cout<<m.trace()<<endl;
cout<<m.minCoeff()<<endl;
}
同时,maxCoeff()、minCoeff()可以换回最大值或者最小值的位置
int max=m.maxCoeff(&i,&j);
5)块操作
函数.block():
operation | 构建一个动态尺寸的block | 构建一个固定尺寸的block |
---|---|---|
起点(i,j)块大小(p,q) | .block(i,j,p,q) | .block< p,q >(i,j) |
注意:
- Eigen中的索引从0开始。
- 两种方式都可以用于固定尺寸和动态尺寸的matrix/array,功能是等价的;
- 区别:只是固定尺寸的版本在block较小时速度更快一些。
int main()
{
Eigen::MatrixXf m(4,4);
m << 1, 2, 3, 4,
5, 6, 7, 8,
9,10,11,12,
13,14,15,16;
cout << "Block in the middle" << endl;
cout << m.block<2,2>(1,1) << endl << endl;
for (int i = 1; i <= 3; ++i)
{
cout << "Block of size " << i << "x" << i << endl;
cout << m.block(0,0,i,i) << endl << endl;
}
}
- 矩阵的其他块。
operation | dynamic-size block | fixed-size block |
---|---|---|
左上角p\*q | matrix.topLeftCorner(p,q); | matrix.topLeftCorner< p,q >(); |
左下角p\*q | matrix.bottomLeftCorner(p,q); | matrix.bottomLeftCorner< p,q >(); |
右上角p\*q | matrix.topRightCorner(p,q); | matrix.topRightCorner< p,q >(); |
右下角p\*q | matrix.bottomRightCorner(p,q); | matrix.bottomRightCorner< p,q >(); |
前q行 | matrix.topRows(q); | matrix.topRows< q >(); |
后q行 | matrix.bottomRows(q); | matrix.bottomRows< q >(); |
左p列 | matrix.leftCols(p); | matrix.leftCols< p >(); |
右p列 | matrix.rightCols(p); | matrix.rightCols< p >(); |
- vector的块
operation | dynamic-size block | fixed-size block |
---|---|---|
前n个 | vector.head(n); | vector.head< n >(); |
后n个 | vector.tail(n); | vector.tail< n >(); |
i起始的n个元素 | vector.segment(i,n); | vector.segment< n >(i); |