转载自:https://blog.csdn.net/r1254/article/details/47418871
以及https://blog.csdn.net/wokaowokaowokao12345/article/details/53397488
第一部分:
1.1前言
Eigen是一个高层次的C ++库,有效支持 得到的线性代数,矩阵和矢量运算,数值分析及其相关的算法。
1.2配置
关于Eigen库的配置只需要在属性表包含目录中添加Eigen路径即可。
1.3例子
Example 1:
-
#include <iostream>
-
#include <Eigen/Dense>
-
-
void main()
-
{
-
Eigen::
MatrixXd m(2, 2);
//声明一个MatrixXd类型的变量,它是2*2的矩阵,未初始化
-
m(
0,
0) =
3;
//将矩阵第1个元素初始化3
-
m(
1,
0) =
2.5;
//将矩阵第3个元素初始化3
-
m(
0,
1) =
-1;
-
m(
1,
1) = m(
1,
0) + m(
0,
1);
-
std::
cout << m <<
std::
endl;
-
}
Eigen头文件定义了很多类型,但对于简单的应用程序,可能只使用MatrixXd类型。 这表示任意大小的矩阵(MatrixXd中的X),其中每个条目是双精度(MatrixXd中的d)。 Eigen / Dense头文件定义了MatrixXd类型和相关类型的所有成员函数。 在这个头文件中定义的所有类和函数都在特征名称空间中。
Example 2:
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
using
namespace
std;
-
int main()
-
{
-
MatrixXd m = MatrixXd::Random(
3,
3);
//使用Random随机初始化3*3的矩阵
-
m = (m + MatrixXd::Constant(
3,
3,
1.2)) *
50;
-
cout <<
"m =" <<
endl << m <<
endl;
-
VectorXd v(3);
//这表示任意大小的(列)向量。
-
v <<
1,
2,
3;
-
cout <<
"m * v =" <<
endl << m * v <<
endl;
-
}
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
using
namespace
std;
-
int main()
-
{
-
Matrix3d m = Matrix3d::Random();
//使用Random随机初始化固定大小的3*3的矩阵
-
m = (m + Matrix3d::Constant(
1.2)) *
50;
-
cout <<
"m =" <<
endl << m <<
endl;
Vector3d v(1,2,3);
-
cout <<
"m * v =" <<
endl << m * v <<
endl;
-
}
Matrix&Vector
Example 3:
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
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 <<
"Here is the matrix m:\n" << m <<
std::
endl;
-
VectorXd v(2);
-
v(
0) =
4;
-
v(
1) = v(
0) -
1;
-
std::
cout <<
"Here is the vector v:\n" << v <<
std::
endl;
-
}
逗号初始化
Example 4:
-
Matrix3f m;
-
m <<
1,
2,
3,
4,
5,
6,
7,
8,
9;
-
std::
cout << m;
通过Resize调整矩阵大小
矩阵的当前大小可以通过rows(),cols()和size()检索。 这些方法分别返回行数,列数和系数数。 通过resize()方法调整动态大小矩阵的大小。
Example 5:
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
int main()
-
{
-
MatrixXd m(2,5);
//初始化大小2*5
-
m.resize(
4,
3);
//重新调整为4*3
-
std::
cout <<
"The matrix m is of size " << m.rows() <<
"x" << m.cols() <<
std::
endl;
-
std::
cout <<
"It has " << m.size() <<
" coefficients" <<
std::
endl;
-
VectorXd v(2); v.resize(
5);
-
std::
cout <<
"The vector v is of size " << v.size() <<
std::
endl;
-
std::
cout <<
"As a matrix, v is of size " << v.rows() <<
"x" << v.cols() <<
std::
endl;
-
}
通过赋值调整矩阵大小
Example 6:
-
MatrixXf a(2, 2);
-
std::
cout <<
"a is of size " << a.rows() <<
"x" << a.cols() <<
std::
endl;
-
MatrixXf b(3, 3);
-
a = b;
-
std::
cout <<
"a is now of size " << a.rows() <<
"x" << a.cols() <<
std::
endl;
Eigen + - * 等运算
Eigen通过通用的C ++算术运算符(例如+, - ,)或通过特殊方法(如dot(),cross()等)的重载提供矩阵/向量算术运算。对于Matrix类(矩阵和向量) 只被重载以支持线性代数运算。 例如,matrix1 matrix2表示矩阵矩阵乘积。
Example 7:
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
int main()
-
{
-
Matrix2d a; a <<
1,
2,
3,
4;
-
MatrixXd b(2,2);
-
b <<
2,
3,
1,
4;
-
std::
cout <<
"a + b =\n" << a + b <<
std::
endl;
-
std::
cout <<
"a - b =\n" << a - b <<
std::
endl;
-
std::
cout <<
"Doing a += b;" <<
std::
endl;
-
a += b;
-
std::
cout <<
"Now a =\n" << a <<
std::
endl;
-
Vector3d v(1,2,3);
-
Vector3d w(1,0,0);
-
std::
cout <<
"-v + w - v =\n" << -v + w - v <<
std::
endl;
-
}
Example 8:
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
int main()
-
{
-
Matrix2d a;
-
a <<
1,
2,
3,
4;
-
Vector3d v(1,2,3);
-
std::
cout <<
"a * 2.5 =\n" << a *
2.5 <<
std::
endl;
-
std::
cout <<
"0.1 * v =\n" <<
0.1 * v <<
std::
endl;
-
std::
cout <<
"Doing v *= 2;" <<
std::
endl; v *=
2;
-
std::
cout <<
"Now v =\n" << v <<
std::
endl;
-
}
矩阵转置、共轭和伴随矩阵
-
MatrixXcf a = MatrixXcf::Random(
2,
2);
-
cout <<
"Here is the matrix a\n" << a <<
endl;
-
cout <<
"Here is the matrix a^T\n" << a.transpose() <<
endl;
-
cout <<
"Here is the conjugate of a\n" << a.conjugate() <<
endl;
-
cout <<
"Here is the matrix a^*\n" << a.adjoint() <<
endl;
禁止如下操作:
a = a.transpose(); // !!! do NOT do this !!!
但是可以使用如下函数:
a.transposeInPlace();
此时a被其转置替换。
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
int main()
-
{
-
Matrix2i a;
-
a <<
1,
2,
3,
4;
-
std::
cout <<
"Here is the matrix a:\n" << a <<
std::
endl;
-
a = a.transpose();
// !!! do NOT do this !!!
-
std::
cout <<
"and the result of the aliasing effect:\n" << a <<
std::
endl;
-
}
矩阵* 矩阵和矩阵* 向量操作
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace
Eigen;
-
int main()
-
{
-
Matrix2d mat; mat <<
1,
2,
3,
4;
-
Vector2d u(
-1,
1), v(
2,
0);
-
std::cout <<
"Here is mat*mat:\n" << mat*mat << std::endl;
-
std::cout <<
"Here is mat*u:\n" << mat*u << std::endl;
-
std::cout <<
"Here is u^T*mat:\n" << u.transpose()*mat << std::endl;
-
std::cout <<
"Here is u^T*v:\n" << u.transpose()*v << std::endl;
-
std::cout <<
"Here is u*v^T:\n" << u*v.transpose() << std::endl;
-
std::cout <<
"Let's multiply mat by itself" << std::endl;
-
mat = mat*mat; std::cout <<
"Now mat is mat:\n" << mat << std::endl;
-
}
点乘和叉乘
对于点积和叉乘积,需要使用dot()和cross()方法。
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
using
namespace
std;
-
int main()
-
{
-
Vector3d v(1,2,3);
-
Vector3d w(0,1,2);
-
cout <<
"Dot product: " << v.dot(w) <<
endl;
-
double dp = v.adjoint()*w;
// automatic conversion of the inner product to a scalar
-
cout <<
"Dot product via a matrix product: " << dp <<
endl;
-
cout <<
"Cross product:\n" << v.cross(w) <<
endl;
-
}
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace
std;
-
int main()
-
{
-
Eigen::Matrix2d mat;
-
mat <<
1,
2,
3,
4;
-
cout <<
"Here is mat.sum(): " << mat.sum() <<
endl;
-
cout <<
"Here is mat.prod(): " << mat.prod() <<
endl;
-
cout <<
"Here is mat.mean(): " << mat.mean() <<
endl;
-
cout <<
"Here is mat.minCoeff(): " << mat.minCoeff() <<
endl;
-
cout <<
"Here is mat.maxCoeff(): " << mat.maxCoeff() <<
endl;
-
cout <<
"Here is mat.trace(): " << mat.trace() <<
endl;
-
}
数组的运算(未完待续)
Eigen最小二乘估计
最小平方求解的最好方法是使用SVD分解。 Eigen提供一个作为JacobiSVD类,它的solve()是做最小二乘解。式子为Ax=b
经过和Matlab对比。
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace
std;
-
using
namespace Eigen;
-
int main()
-
{
-
MatrixXf A = MatrixXf::Random(
3,
2);
-
cout <<
"Here is the matrix A:\n" << A <<
endl;
-
VectorXf b = VectorXf::Random(
3);
-
cout <<
"Here is the right hand side b:\n" << b <<
endl;
-
cout <<
"The least-squares solution is:\n" << A.jacobiSvd(ComputeThinU | ComputeThinV).solve(b) <<
endl;
-
}
第二部分:
矩阵、向量初始化
-
#include <iostream>
-
#include "Eigen/Dense"
-
using
namespace Eigen;
-
int main()
-
{
-
MatrixXf m1(3,4);
//动态矩阵,建立3行4列。
-
MatrixXf m2(4,3);
//4行3列,依此类推。
-
MatrixXf m3(3,3);
-
-
Vector3f v1;
//若是静态数组,则不用指定行或者列
-
/* 初始化 */
-
Matrix3d m = Matrix3d::Random();
-
m1 = MatrixXf::Zero(
3,
4);
//用0矩阵初始化,要指定行列数
-
m2 = MatrixXf::Zero(
4,
3);
-
m3 = MatrixXf::Identity(
3,
3);
//用单位矩阵初始化
-
v1 = Vector3f::Zero();
//同理,若是静态的,不用指定行列数
-
-
m1 <<
1,
0,
0,
1,
//也可以以这种方式初始化
-
1,
5,
0,
1,
-
0,
0,
9,
1;
-
m2 <<
1,
0,
0,
-
0,
4,
0,
-
0,
0,
7,
-
1,
1,
1;
-
//向量初始化,与矩阵类似
-
Vector3d v3(1,2,3);
-
VectorXf vx(30);
-
}
C++数组和矩阵转换
使用Map函数,可以实现Eigen的矩阵和c++中的数组直接转换,语法如下:
-
//@param MatrixType 矩阵类型
-
//@param MapOptions 可选参数,指的是指针是否对齐,Aligned, or Unaligned. The default is Unaligned.
-
//@param StrideType 可选参数,步长
-
/*
-
Map<typename MatrixType,
-
int MapOptions,
-
typename StrideType>
-
*/
-
int i;
-
//数组转矩阵
-
double *aMat =
new
double[
20];
-
for(i =
0;i<
20;i++)
-
{
-
aMat[i] = rand()%
11;
-
}
-
//静态矩阵,编译时确定维数 Matrix<double,4,5>
-
Eigen:Map<Matrix<
double,
4,
5> > staMat(aMat);
-
-
-
//输出
-
for (
int i =
0; i < staMat.size(); i++)
-
std::
cout << *(staMat.data() + i) <<
" ";
-
std::
cout <<
std::
endl <<
std::
endl;
-
-
-
//动态矩阵,运行时确定 MatrixXd
-
Map<MatrixXd> dymMat(aMat,
4,
5);
-
-
-
//输出,应该和上面一致
-
for (
int i =
0; i < dymMat.size(); i++)
-
std::
cout << *(dymMat.data() + i) <<
" ";
-
std::
cout <<
std::
endl <<
std::
endl;
-
-
//Matrix中的数据存在一维数组中,默认是行优先的格式,即一行行的存
-
//data()返回Matrix中的指针
-
dymMat.data();
矩阵基础操作
eigen重载了基础的+ - * / += -= = /= 可以表示标量和矩阵或者矩阵和矩阵
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
int main()
-
{
-
//单个取值,单个赋值
-
double value00 = staMat(
0,
0);
-
double value10 = staMat(
1,
0);
-
staMat(
0,
0) =
100;
-
std::
cout << value00 <<value10<<
std::
endl;
-
std::
cout <<staMat<<
std::
endl<<
std::
endl;
-
//加减乘除示例 Matrix2d 等同于 Matrix<double,2,2>
-
Matrix2d a;
-
a <<
1,
2,
-
3,
4;
-
MatrixXd b(2,2);
-
b <<
2,
3,
-
1,
4;
-
-
Matrix2d c = a + b;
-
std::
cout<< c<<
std::
endl<<
std::
endl;
-
-
c = a - b;
-
std::
cout<<c<<
std::
endl<<
std::
endl;
-
-
c = a *
2;
-
std::
cout<<c<<
std::
endl<<
std::
endl;
-
-
c =
2.5 * a;
-
std::
cout<<c<<
std::
endl<<
std::
endl;
-
-
c = a /
2;
-
std::
cout<<c<<
std::
endl<<
std::
endl;
-
-
c = a * b;
-
std::
cout<<c<<
std::
endl<<
std::
endl;
点积和叉积
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
using
namespace
std;
-
int main()
-
{
-
//点积、叉积(针对向量的)
-
Vector3d v(1,2,3);
-
Vector3d w(0,1,2);
-
std::
cout<<v.dot(w)<<
std::
endl<<
std::
endl;
-
std::
cout<<w.cross(v)<<
std::
endl<<
std::
endl;
-
}
-
*/
转置、伴随、行列式、逆矩阵
小矩阵(4 * 4及以下)eigen会自动优化,默认采用LU分解,效率不高
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace
std;
-
using
namespace Eigen;
-
int main()
-
{
-
Matrix2d c;
-
c <<
1,
2,
-
3,
4;
-
//转置、伴随
-
std::
cout<<c<<
std::
endl<<
std::
endl;
-
std::
cout<<
"转置\n"<<c.transpose()<<
std::
endl<<
std::
endl;
-
std::
cout<<
"伴随\n"<<c.adjoint()<<
std::
endl<<
std::
endl;
-
//逆矩阵、行列式
-
std::
cout <<
"行列式: " << c.determinant() <<
std::
endl;
-
std::
cout <<
"逆矩阵\n" << c.inverse() <<
std::
endl;
-
}
计算特征值和特征向量
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace
std;
-
using
namespace Eigen;
-
int main()
-
{
-
//特征向量、特征值
-
std::
cout <<
"Here is the matrix A:\n" << a <<
std::
endl;
-
SelfAdjointEigenSolver<Matrix2d> eigensolver(a);
-
if (eigensolver.info() != Success)
abort();
-
std::
cout <<
"特征值:\n" << eigensolver.eigenvalues() <<
std::
endl;
-
std::
cout <<
"Here's a matrix whose columns are eigenvectors of A \n"
-
<<
"corresponding to these eigenvalues:\n"
-
<< eigensolver.eigenvectors() <<
std::
endl;
-
}
解线性方程
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace
std;
-
using
namespace Eigen;
-
int main()
-
{
-
//线性方程求解 Ax =B;
-
Matrix4d A;
-
A <<
2,
-1,
-1,
1,
-
1,
1,
-2,
1,
-
4,
-6,
2,
-2,
-
3,
6,
-9,
7;
-
-
Vector4d B(2,4,4,9);
-
-
Vector4d x = A.colPivHouseholderQr().solve(B);
-
Vector4d x2 = A.llt().solve(B);
-
Vector4d x3 = A.ldlt().solve(B);
-
-
-
std::
cout <<
"The solution is:\n" << x <<
"\n\n"<<x2<<
"\n\n"<<x3 <<
std::
endl;
-
}
除了colPivHouseholderQr、LLT、LDLT,还有以下的函数可以求解线性方程组,请注意精度和速度: 解小矩阵(4*4)基本没有速度差别
最小二乘求解
最小二乘求解有两种方式,jacobiSvd或者colPivHouseholderQr,4*4以下的小矩阵速度没有区别,jacobiSvd可能更快,大矩阵最好用colPivHouseholderQr
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace
std;
-
using
namespace Eigen;
-
int main()
-
{
-
MatrixXf A1 = MatrixXf::Random(
3,
2);
-
std::
cout <<
"Here is the matrix A:\n" << A1 <<
std::
endl;
-
VectorXf b1 = VectorXf::Random(
3);
-
std::
cout <<
"Here is the right hand side b:\n" << b1 <<
std::
endl;
-
//jacobiSvd 方式:Slow (but fast for small matrices)
-
std::
cout <<
"The least-squares solution is:\n"
-
<< A1.jacobiSvd(ComputeThinU | ComputeThinV).solve(b1) <<
std::
endl;
-
//colPivHouseholderQr方法:fast
-
std::
cout <<
"The least-squares solution is:\n"
-
<< A1.colPivHouseholderQr().solve(b1) <<
std::
endl;
-
}
稀疏矩阵
稀疏矩阵的头文件包括:
#include
-
typedef Eigen::Triplet<
double> T;
-
std::
vector<T> tripletList;
-
triplets.reserve(estimation_of_entries);
//estimation_of_entries是预估的条目
-
for(...)
-
{
-
tripletList.push_back(T(i,j,v_ij));
//第 i,j个有值的位置的值
-
}
-
SparseMatrixType mat(rows,cols);
-
mat.setFromTriplets(tripletList.begin(), tripletList.end());
-
// mat is ready to go!
2.直接将已知的非0值插入
-
SparseMatrix<double> mat(rows,cols);
-
mat.reserve(VectorXi::Constant(cols,
6));
-
for(...)
-
{
-
// i,j 个非零值 v_ij != 0
-
mat.insert(i,j) = v_ij;
-
}
-
mat.makeCompressed();
// optional
稀疏矩阵支持大部分一元和二元运算:
sm1.real() sm1.imag() -sm1 0.5*sm1
sm1+sm2 sm1-sm2 sm1.cwiseProduct(sm2)
二元运算中,稀疏矩阵和普通矩阵可以混合使用
//dm表示普通矩阵
dm2 = sm1 + dm1;
也支持计算转置矩阵和伴随矩阵
参考以下链接
第三部分:
其他相关博客:
1、单独下载与安装:https://blog.csdn.net/augusdi/article/details/12907341
2、一篇较详细的教程:https://blog.csdn.net/wzaltzap/article/details/79501856
3、计算特征值特征向量:https://blog.csdn.net/wokaowokaowokao12345/article/details/47375427
</div>
转载自:https://blog.csdn.net/r1254/article/details/47418871
以及https://blog.csdn.net/wokaowokaowokao12345/article/details/53397488
第一部分:
1.1前言
Eigen是一个高层次的C ++库,有效支持 得到的线性代数,矩阵和矢量运算,数值分析及其相关的算法。
1.2配置
关于Eigen库的配置只需要在属性表包含目录中添加Eigen路径即可。
1.3例子
Example 1:
-
#include <iostream>
-
#include <Eigen/Dense>
-
-
void main()
-
{
-
Eigen::
MatrixXd m(2, 2);
//声明一个MatrixXd类型的变量,它是2*2的矩阵,未初始化
-
m(
0,
0) =
3;
//将矩阵第1个元素初始化3
-
m(
1,
0) =
2.5;
//将矩阵第3个元素初始化3
-
m(
0,
1) =
-1;
-
m(
1,
1) = m(
1,
0) + m(
0,
1);
-
std::
cout << m <<
std::
endl;
-
}
Eigen头文件定义了很多类型,但对于简单的应用程序,可能只使用MatrixXd类型。 这表示任意大小的矩阵(MatrixXd中的X),其中每个条目是双精度(MatrixXd中的d)。 Eigen / Dense头文件定义了MatrixXd类型和相关类型的所有成员函数。 在这个头文件中定义的所有类和函数都在特征名称空间中。
Example 2:
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
using
namespace
std;
-
int main()
-
{
-
MatrixXd m = MatrixXd::Random(
3,
3);
//使用Random随机初始化3*3的矩阵
-
m = (m + MatrixXd::Constant(
3,
3,
1.2)) *
50;
-
cout <<
"m =" <<
endl << m <<
endl;
-
VectorXd v(3);
//这表示任意大小的(列)向量。
-
v <<
1,
2,
3;
-
cout <<
"m * v =" <<
endl << m * v <<
endl;
-
}
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
using
namespace
std;
-
int main()
-
{
-
Matrix3d m = Matrix3d::Random();
//使用Random随机初始化固定大小的3*3的矩阵
-
m = (m + Matrix3d::Constant(
1.2)) *
50;
-
cout <<
"m =" <<
endl << m <<
endl;
Vector3d v(1,2,3);
-
cout <<
"m * v =" <<
endl << m * v <<
endl;
-
}
Matrix&Vector
Example 3:
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
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 <<
"Here is the matrix m:\n" << m <<
std::
endl;
-
VectorXd v(2);
-
v(
0) =
4;
-
v(
1) = v(
0) -
1;
-
std::
cout <<
"Here is the vector v:\n" << v <<
std::
endl;
-
}
逗号初始化
Example 4:
-
Matrix3f m;
-
m <<
1,
2,
3,
4,
5,
6,
7,
8,
9;
-
std::
cout << m;
通过Resize调整矩阵大小
矩阵的当前大小可以通过rows(),cols()和size()检索。 这些方法分别返回行数,列数和系数数。 通过resize()方法调整动态大小矩阵的大小。
Example 5:
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
int main()
-
{
-
MatrixXd m(2,5);
//初始化大小2*5
-
m.resize(
4,
3);
//重新调整为4*3
-
std::
cout <<
"The matrix m is of size " << m.rows() <<
"x" << m.cols() <<
std::
endl;
-
std::
cout <<
"It has " << m.size() <<
" coefficients" <<
std::
endl;
-
VectorXd v(2); v.resize(
5);
-
std::
cout <<
"The vector v is of size " << v.size() <<
std::
endl;
-
std::
cout <<
"As a matrix, v is of size " << v.rows() <<
"x" << v.cols() <<
std::
endl;
-
}
通过赋值调整矩阵大小
Example 6:
-
MatrixXf a(2, 2);
-
std::
cout <<
"a is of size " << a.rows() <<
"x" << a.cols() <<
std::
endl;
-
MatrixXf b(3, 3);
-
a = b;
-
std::
cout <<
"a is now of size " << a.rows() <<
"x" << a.cols() <<
std::
endl;
Eigen + - * 等运算
Eigen通过通用的C ++算术运算符(例如+, - ,)或通过特殊方法(如dot(),cross()等)的重载提供矩阵/向量算术运算。对于Matrix类(矩阵和向量) 只被重载以支持线性代数运算。 例如,matrix1 matrix2表示矩阵矩阵乘积。
Example 7:
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
int main()
-
{
-
Matrix2d a; a <<
1,
2,
3,
4;
-
MatrixXd b(2,2);
-
b <<
2,
3,
1,
4;
-
std::
cout <<
"a + b =\n" << a + b <<
std::
endl;
-
std::
cout <<
"a - b =\n" << a - b <<
std::
endl;
-
std::
cout <<
"Doing a += b;" <<
std::
endl;
-
a += b;
-
std::
cout <<
"Now a =\n" << a <<
std::
endl;
-
Vector3d v(1,2,3);
-
Vector3d w(1,0,0);
-
std::
cout <<
"-v + w - v =\n" << -v + w - v <<
std::
endl;
-
}
Example 8:
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
int main()
-
{
-
Matrix2d a;
-
a <<
1,
2,
3,
4;
-
Vector3d v(1,2,3);
-
std::
cout <<
"a * 2.5 =\n" << a *
2.5 <<
std::
endl;
-
std::
cout <<
"0.1 * v =\n" <<
0.1 * v <<
std::
endl;
-
std::
cout <<
"Doing v *= 2;" <<
std::
endl; v *=
2;
-
std::
cout <<
"Now v =\n" << v <<
std::
endl;
-
}
矩阵转置、共轭和伴随矩阵
-
MatrixXcf a = MatrixXcf::Random(
2,
2);
-
cout <<
"Here is the matrix a\n" << a <<
endl;
-
cout <<
"Here is the matrix a^T\n" << a.transpose() <<
endl;
-
cout <<
"Here is the conjugate of a\n" << a.conjugate() <<
endl;
-
cout <<
"Here is the matrix a^*\n" << a.adjoint() <<
endl;
禁止如下操作:
a = a.transpose(); // !!! do NOT do this !!!
但是可以使用如下函数:
a.transposeInPlace();
此时a被其转置替换。
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
int main()
-
{
-
Matrix2i a;
-
a <<
1,
2,
3,
4;
-
std::
cout <<
"Here is the matrix a:\n" << a <<
std::
endl;
-
a = a.transpose();
// !!! do NOT do this !!!
-
std::
cout <<
"and the result of the aliasing effect:\n" << a <<
std::
endl;
-
}
矩阵* 矩阵和矩阵* 向量操作
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace
Eigen;
-
int main()
-
{
-
Matrix2d mat; mat <<
1,
2,
3,
4;
-
Vector2d u(
-1,
1), v(
2,
0);
-
std::cout <<
"Here is mat*mat:\n" << mat*mat << std::endl;
-
std::cout <<
"Here is mat*u:\n" << mat*u << std::endl;
-
std::cout <<
"Here is u^T*mat:\n" << u.transpose()*mat << std::endl;
-
std::cout <<
"Here is u^T*v:\n" << u.transpose()*v << std::endl;
-
std::cout <<
"Here is u*v^T:\n" << u*v.transpose() << std::endl;
-
std::cout <<
"Let's multiply mat by itself" << std::endl;
-
mat = mat*mat; std::cout <<
"Now mat is mat:\n" << mat << std::endl;
-
}
点乘和叉乘
对于点积和叉乘积,需要使用dot()和cross()方法。
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
using
namespace
std;
-
int main()
-
{
-
Vector3d v(1,2,3);
-
Vector3d w(0,1,2);
-
cout <<
"Dot product: " << v.dot(w) <<
endl;
-
double dp = v.adjoint()*w;
// automatic conversion of the inner product to a scalar
-
cout <<
"Dot product via a matrix product: " << dp <<
endl;
-
cout <<
"Cross product:\n" << v.cross(w) <<
endl;
-
}
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace
std;
-
int main()
-
{
-
Eigen::Matrix2d mat;
-
mat <<
1,
2,
3,
4;
-
cout <<
"Here is mat.sum(): " << mat.sum() <<
endl;
-
cout <<
"Here is mat.prod(): " << mat.prod() <<
endl;
-
cout <<
"Here is mat.mean(): " << mat.mean() <<
endl;
-
cout <<
"Here is mat.minCoeff(): " << mat.minCoeff() <<
endl;
-
cout <<
"Here is mat.maxCoeff(): " << mat.maxCoeff() <<
endl;
-
cout <<
"Here is mat.trace(): " << mat.trace() <<
endl;
-
}
数组的运算(未完待续)
Eigen最小二乘估计
最小平方求解的最好方法是使用SVD分解。 Eigen提供一个作为JacobiSVD类,它的solve()是做最小二乘解。式子为Ax=b
经过和Matlab对比。
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace
std;
-
using
namespace Eigen;
-
int main()
-
{
-
MatrixXf A = MatrixXf::Random(
3,
2);
-
cout <<
"Here is the matrix A:\n" << A <<
endl;
-
VectorXf b = VectorXf::Random(
3);
-
cout <<
"Here is the right hand side b:\n" << b <<
endl;
-
cout <<
"The least-squares solution is:\n" << A.jacobiSvd(ComputeThinU | ComputeThinV).solve(b) <<
endl;
-
}
第二部分:
矩阵、向量初始化
-
#include <iostream>
-
#include "Eigen/Dense"
-
using
namespace Eigen;
-
int main()
-
{
-
MatrixXf m1(3,4);
//动态矩阵,建立3行4列。
-
MatrixXf m2(4,3);
//4行3列,依此类推。
-
MatrixXf m3(3,3);
-
-
Vector3f v1;
//若是静态数组,则不用指定行或者列
-
/* 初始化 */
-
Matrix3d m = Matrix3d::Random();
-
m1 = MatrixXf::Zero(
3,
4);
//用0矩阵初始化,要指定行列数
-
m2 = MatrixXf::Zero(
4,
3);
-
m3 = MatrixXf::Identity(
3,
3);
//用单位矩阵初始化
-
v1 = Vector3f::Zero();
//同理,若是静态的,不用指定行列数
-
-
m1 <<
1,
0,
0,
1,
//也可以以这种方式初始化
-
1,
5,
0,
1,
-
0,
0,
9,
1;
-
m2 <<
1,
0,
0,
-
0,
4,
0,
-
0,
0,
7,
-
1,
1,
1;
-
//向量初始化,与矩阵类似
-
Vector3d v3(1,2,3);
-
VectorXf vx(30);
-
}
C++数组和矩阵转换
使用Map函数,可以实现Eigen的矩阵和c++中的数组直接转换,语法如下:
-
//@param MatrixType 矩阵类型
-
//@param MapOptions 可选参数,指的是指针是否对齐,Aligned, or Unaligned. The default is Unaligned.
-
//@param StrideType 可选参数,步长
-
/*
-
Map<typename MatrixType,
-
int MapOptions,
-
typename StrideType>
-
*/
-
int i;
-
//数组转矩阵
-
double *aMat =
new
double[
20];
-
for(i =
0;i<
20;i++)
-
{
-
aMat[i] = rand()%
11;
-
}
-
//静态矩阵,编译时确定维数 Matrix<double,4,5>
-
Eigen:Map<Matrix<
double,
4,
5> > staMat(aMat);
-
-
-
//输出
-
for (
int i =
0; i < staMat.size(); i++)
-
std::
cout << *(staMat.data() + i) <<
" ";
-
std::
cout <<
std::
endl <<
std::
endl;
-
-
-
//动态矩阵,运行时确定 MatrixXd
-
Map<MatrixXd> dymMat(aMat,
4,
5);
-
-
-
//输出,应该和上面一致
-
for (
int i =
0; i < dymMat.size(); i++)
-
std::
cout << *(dymMat.data() + i) <<
" ";
-
std::
cout <<
std::
endl <<
std::
endl;
-
-
//Matrix中的数据存在一维数组中,默认是行优先的格式,即一行行的存
-
//data()返回Matrix中的指针
-
dymMat.data();
矩阵基础操作
eigen重载了基础的+ - * / += -= = /= 可以表示标量和矩阵或者矩阵和矩阵
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
int main()
-
{
-
//单个取值,单个赋值
-
double value00 = staMat(
0,
0);
-
double value10 = staMat(
1,
0);
-
staMat(
0,
0) =
100;
-
std::
cout << value00 <<value10<<
std::
endl;
-
std::
cout <<staMat<<
std::
endl<<
std::
endl;
-
//加减乘除示例 Matrix2d 等同于 Matrix<double,2,2>
-
Matrix2d a;
-
a <<
1,
2,
-
3,
4;
-
MatrixXd b(2,2);
-
b <<
2,
3,
-
1,
4;
-
-
Matrix2d c = a + b;
-
std::
cout<< c<<
std::
endl<<
std::
endl;
-
-
c = a - b;
-
std::
cout<<c<<
std::
endl<<
std::
endl;
-
-
c = a *
2;
-
std::
cout<<c<<
std::
endl<<
std::
endl;
-
-
c =
2.5 * a;
-
std::
cout<<c<<
std::
endl<<
std::
endl;
-
-
c = a /
2;
-
std::
cout<<c<<
std::
endl<<
std::
endl;
-
-
c = a * b;
-
std::
cout<<c<<
std::
endl<<
std::
endl;
点积和叉积
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace Eigen;
-
using
namespace
std;
-
int main()
-
{
-
//点积、叉积(针对向量的)
-
Vector3d v(1,2,3);
-
Vector3d w(0,1,2);
-
std::
cout<<v.dot(w)<<
std::
endl<<
std::
endl;
-
std::
cout<<w.cross(v)<<
std::
endl<<
std::
endl;
-
}
-
*/
转置、伴随、行列式、逆矩阵
小矩阵(4 * 4及以下)eigen会自动优化,默认采用LU分解,效率不高
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace
std;
-
using
namespace Eigen;
-
int main()
-
{
-
Matrix2d c;
-
c <<
1,
2,
-
3,
4;
-
//转置、伴随
-
std::
cout<<c<<
std::
endl<<
std::
endl;
-
std::
cout<<
"转置\n"<<c.transpose()<<
std::
endl<<
std::
endl;
-
std::
cout<<
"伴随\n"<<c.adjoint()<<
std::
endl<<
std::
endl;
-
//逆矩阵、行列式
-
std::
cout <<
"行列式: " << c.determinant() <<
std::
endl;
-
std::
cout <<
"逆矩阵\n" << c.inverse() <<
std::
endl;
-
}
计算特征值和特征向量
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace
std;
-
using
namespace Eigen;
-
int main()
-
{
-
//特征向量、特征值
-
std::
cout <<
"Here is the matrix A:\n" << a <<
std::
endl;
-
SelfAdjointEigenSolver<Matrix2d> eigensolver(a);
-
if (eigensolver.info() != Success)
abort();
-
std::
cout <<
"特征值:\n" << eigensolver.eigenvalues() <<
std::
endl;
-
std::
cout <<
"Here's a matrix whose columns are eigenvectors of A \n"
-
<<
"corresponding to these eigenvalues:\n"
-
<< eigensolver.eigenvectors() <<
std::
endl;
-
}
解线性方程
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace
std;
-
using
namespace Eigen;
-
int main()
-
{
-
//线性方程求解 Ax =B;
-
Matrix4d A;
-
A <<
2,
-1,
-1,
1,
-
1,
1,
-2,
1,
-
4,
-6,
2,
-2,
-
3,
6,
-9,
7;
-
-
Vector4d B(2,4,4,9);
-
-
Vector4d x = A.colPivHouseholderQr().solve(B);
-
Vector4d x2 = A.llt().solve(B);
-
Vector4d x3 = A.ldlt().solve(B);
-
-
-
std::
cout <<
"The solution is:\n" << x <<
"\n\n"<<x2<<
"\n\n"<<x3 <<
std::
endl;
-
}
除了colPivHouseholderQr、LLT、LDLT,还有以下的函数可以求解线性方程组,请注意精度和速度: 解小矩阵(4*4)基本没有速度差别
最小二乘求解
最小二乘求解有两种方式,jacobiSvd或者colPivHouseholderQr,4*4以下的小矩阵速度没有区别,jacobiSvd可能更快,大矩阵最好用colPivHouseholderQr
-
#include <iostream>
-
#include <Eigen/Dense>
-
using
namespace
std;
-
using
namespace Eigen;
-
int main()
-
{
-
MatrixXf A1 = MatrixXf::Random(
3,
2);
-
std::
cout <<
"Here is the matrix A:\n" << A1 <<
std::
endl;
-
VectorXf b1 = VectorXf::Random(
3);
-
std::
cout <<
"Here is the right hand side b:\n" << b1 <<
std::
endl;
-
//jacobiSvd 方式:Slow (but fast for small matrices)
-
std::
cout <<
"The least-squares solution is:\n"
-
<< A1.jacobiSvd(ComputeThinU | ComputeThinV).solve(b1) <<
std::
endl;
-
//colPivHouseholderQr方法:fast
-
std::
cout <<
"The least-squares solution is:\n"
-
<< A1.colPivHouseholderQr().solve(b1) <<
std::
endl;
-
}
稀疏矩阵
稀疏矩阵的头文件包括:
#include
-
typedef Eigen::Triplet<
double> T;
-
std::
vector<T> tripletList;
-
triplets.reserve(estimation_of_entries);
//estimation_of_entries是预估的条目
-
for(...)
-
{
-
tripletList.push_back(T(i,j,v_ij));
//第 i,j个有值的位置的值
-
}
-
SparseMatrixType mat(rows,cols);
-
mat.setFromTriplets(tripletList.begin(), tripletList.end());
-
// mat is ready to go!
2.直接将已知的非0值插入
-
SparseMatrix<double> mat(rows,cols);
-
mat.reserve(VectorXi::Constant(cols,
6));
-
for(...)
-
{
-
// i,j 个非零值 v_ij != 0
-
mat.insert(i,j) = v_ij;
-
}
-
mat.makeCompressed();
// optional
稀疏矩阵支持大部分一元和二元运算:
sm1.real() sm1.imag() -sm1 0.5*sm1
sm1+sm2 sm1-sm2 sm1.cwiseProduct(sm2)
二元运算中,稀疏矩阵和普通矩阵可以混合使用
//dm表示普通矩阵
dm2 = sm1 + dm1;
也支持计算转置矩阵和伴随矩阵
参考以下链接
第三部分:
其他相关博客:
1、单独下载与安装:https://blog.csdn.net/augusdi/article/details/12907341
2、一篇较详细的教程:https://blog.csdn.net/wzaltzap/article/details/79501856
3、计算特征值特征向量:https://blog.csdn.net/wokaowokaowokao12345/article/details/47375427
</div>