赞
踩
这一小节主要介绍Eigen库对于矩阵运算的一些支持,基本和matlab里运算操作一致,便于数据运算,常见的包括矩阵的加减、矩阵的乘法、矩阵的转置与共轭等操作,下面将逐一介绍所有的操作符。
Eigen中进行矩阵的加减操作需要满足两点条件:1.进行加减操作的矩阵变量具有相同的尺寸(行和列);2.矩阵的元素类型相同(Eigen不自动转化类型),具体可以看下面的代码例子:
#include <iostream> #include <Eigen/Dense> using namespace Eigen; int main() { Eigen::Matrix2d a; //定义一个2维矩阵 a << 1,2, //矩阵赋值 3,4; Eigen::Matrix2d b; b << 2,3, 1,4; std::cout << "a + b =\n" << a + b << std::endl; //执行矩阵 a+b std::cout << "**************************" << std::endl; std::cout << "a + b =\n" << a - b << std::endl; //执行矩阵 a-b std::cout << "**************************" << std::endl; a += b; std::cout << "执行a += b\n" << "现在a=\n" << a << std::endl; //执行矩阵 a+=b,会将结果赋值给a std::cout << "**************************" << std::endl; Eigen::Vector3d v(1, 2, 3); //定义3维列向量 Eigen::Vector3d w(1, 0, 0); std::cout << "-v + w -v =\n" << -v + w -v << std::endl; }
特别注意执行 a+=b 的操作后会将结果赋值给a,下面是程序的输出结果:
a + b = 3 5 4 8 ************************** a + b = -1 -1 2 0 ************************** 执行a += b 现在a= 3 5 4 8 ************************** -v + w -v = -1 -4 -6
Eigen中对于矩阵的运算可以直接对矩阵与标量进行乘除法,相当于对矩阵中每个元素都进行乘除法,具体的内容看下面的代码:
#include <iostream> #include <Eigen/Dense> using namespace Eigen; int main() { Eigen::Matrix2d a; //定义一个2维矩阵 a << 1,2, //矩阵赋值 3,4; Eigen::Vector3d v(1, 2, 3); //定义3维列向量 std::cout << "a * 2.5 =\n" << a * 2.5 << std::endl; //执行矩阵 a * 2.5 std::cout << "**************************" << std::endl; std::cout << "0.1 * v =\n" << 0.1 * v << std::endl; //执行 0.1 * v std::cout << "**************************" << std::endl; v *= 2; std::cout << "执行v *= 2\n" << "现在v=\n" << v << std::endl; //执行向量 v *= 2,会将结果赋值给v }
特别注意执行 v *= 2的操作后会将结果赋值给v,下面是程序的输出结果:
a * 2.5 =
2.5 5
7.5 10
**************************
0.1 * v =
0.1
0.2
0.3
**************************
执行v *= 2
现在v=
2
4
6
Eigen库除了支持矩阵与标量的乘法,还支持矩阵与矩阵间的乘法,前提是满足矩阵乘法的维度大小,即满足a(m*n)b(nk)的形式,具体用法看下面的代码:
#include <iostream> #include <Eigen/Dense> using namespace Eigen; int main() { Eigen::Matrix2d a; //定义一个2维矩阵 a << 1,2, //矩阵赋值 3,4; Eigen::Vector2d u(-1, 1), v(2, 0); //定义2维列向量 std::cout << "a * a =\n" << a * a << std::endl; //执行矩阵 a * a std::cout << "**************************" << std::endl; std::cout << "a * u =\n" << a * u << std::endl; //执行 a * u std::cout << "**************************" << std::endl; std::cout << "u^T * a =\n" << u.transpose() * a <<std::endl; //执行 u^T * a std::cout << "**************************" << std::endl; std::cout << "u^T * v =\n" << u.transpose() * v <<std::endl; //执行 u^T * v std::cout << "**************************" << std::endl; std::cout << "u * v^T =\n" << u * v.transpose() <<std::endl; //执行 u * v^T std::cout << "**************************" << std::endl; a = a * a; std::cout << "执行 a = a * a\n" << "现在a=\n" << a << std::endl; }
这个程序的输出结果如下:
a * a = 7 10 15 22 ************************** a * u = 1 1 ************************** u^T * a = 2 2 ************************** u^T * v = -2 ************************** u * v^T = -2 -0 2 0 ************************** 执行 a = a * a 现在a= 7 10 15 22
在Eigen库中,dot()执行点积,cross()执行叉积,点运算得到1*1的矩阵。
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
Eigen::Vector3d u(1, 2, 3), v(0, 1, 2); //定义2维列向量
std::cout << "点乘:" << u.dot(v) << std::endl; //执行点乘
std::cout << "**************************" << std::endl;
std::cout << "叉乘:\n" << u.cross(v) << std::endl; //执行叉乘
}
输出的结果如下:
点乘:8
**************************
叉乘:
1
-2
1
具体用法看下面的示例代码:
#include <iostream> #include <Eigen/Dense> using namespace Eigen; int main() { Eigen::MatrixXcf a = MatrixXcf::Random(2,2); //定义一个复数矩阵:MatrixXcf std::cout << "***************************" << std::endl; std::cout << "矩阵 a\n" << a << std::endl; std::cout << "***************************" << std::endl; std::cout << "矩阵 a 的转置 a^T\n" << a.transpose() << std::endl; std::cout << "***************************" << std::endl; std::cout << "矩阵 a 的共轭\n" << a.conjugate() << std::endl; std::cout << "***************************" << std::endl; std::cout << "矩阵 a 的共轭转置 a^*\n" << a.adjoint() << std::endl; std::cout << "***************************" << std::endl; }
输出结果如下:
*************************** 矩阵 a (-0.211234,0.680375) (-0.604897,0.823295) (0.59688,0.566198) (0.536459,-0.329554) *************************** 矩阵 a 的转置 a^T (-0.211234,0.680375) (0.59688,0.566198) (-0.604897,0.823295) (0.536459,-0.329554) *************************** 矩阵 a 的共轭 (-0.211234,-0.680375) (-0.604897,-0.823295) (0.59688,-0.566198) (0.536459,0.329554) *************************** 矩阵 a 的共轭转置 a^* (-0.211234,-0.680375) (0.59688,-0.566198) (-0.604897,-0.823295) (0.536459,0.329554) ***************************
注意共轭操作仅对复数矩阵有用,对于实数矩阵,共轭不执行任何操作,转置共轭操作等价于转置操作。
转置和共轭转置会返回一个代理对象并不对本身做转置。如果执行 b=a.transpose() ,a不变,转置结果被赋值给b。如果执行 a=a.transpose() ,Eigen在转置结束之前结果会开始写入a,所以a的最终结果不一定等于a的转置。切记千万不要这样做!!!!!!!!!
Eigen库中提供了而一些归约函数:sum()、prod()、maxCoeff()和minCoeff(),他们都是对矩阵的所有元素进行操作。
具体的使用案例看下面的代码例子:
#include <iostream> #include <Eigen/Dense> using namespace Eigen; int main() { Eigen::Matrix2d mat; //定义一个2维矩阵 mat << 1, 2, //给2位矩阵赋值 3, 4; std::cout << "***************************" << std::endl; std::cout << "mat.sum(): " << mat.sum() << std::endl; std::cout << "***************************" << std::endl; std::cout << "mat.prod(): " << mat.prod() << std::endl; std::cout << "***************************" << std::endl; std::cout << "mat.mean(): " << mat.mean() << std::endl; std::cout << "***************************" << std::endl; std::cout << "mat.minCoeff(): " << mat.minCoeff() << std::endl; std::cout << "***************************" << std::endl; std::cout << "mat.maxCoeff(): " << mat.maxCoeff() << std::endl; std::cout << "***************************" << std::endl; std::cout << "mat.trace(): " << mat.trace() << std::endl; std::cout << "***************************" << std::endl; }
输出结果为:
***************************
mat.sum(): 10
***************************
mat.prod(): 24
***************************
mat.mean(): 2.5
***************************
mat.minCoeff(): 1
***************************
mat.maxCoeff(): 4
***************************
mat.trace(): 5
***************************
在Eigen中,线性运算比如+不会对变量自身做任何操作,会返回一个“表达式对象”来描述被执行的计算。当整个表达式被评估完(一般是遇到=号),实际的操作才执行。
这样做主要是为了优化,比如:
VectorXf a(50), b(50), c(50), d(50);
...
a = 3*b + 4*c + 5*d;
Eigen会编译这段代码最终遍历一次即可运算完成,因此,我们不必要担心大的线性表达式的运算效率。
for(int i = 0; i < 50; ++i)
a[i] = 3*b[i] + 4*c[i] + 5*d[i];
Eigen会检测执行操作的有效性,在编译阶段Eigen会检测它们,错误信息是繁冗的,但错误信息会大写字母突出,比如:
Matrix3f m;
Vector4f v;
v = m*v; // Compile-time error: YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES
当然动态尺寸的错误要在运行时发现,如果在debug模式,assertions会触发后,程序将崩溃。
MatrixXf m(3,3);
VectorXf v(4);
v = m * v; // Run-time assertion failure here: "invalid matrix product"
更多技术欢迎加入交流:320297153
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。