当前位置:   article > 正文

C++线性代数库Eigen简明教程_eigen c++

eigen c++

线性代数在3D游戏建模、深度学习、机器人工程、视频图像处理、航空航天等领域都有着举足轻重的位置。在使用C++编程时,如果从零编写矩阵的乘法、求逆、求特征值等运算,将会是件很麻烦的事情。而且,不管是从计算正确性,还是从效率方面都很难得到保障。因此,成熟稳定的线性代数库显得尤为重要。

Eigen是线性代数的C++模板库,它包含矩阵、向量、四元数、数值求解器和相关算法,其拥有良好的稳定性和计算效率,是我们搭建C++工程研究算法的必备利器。

目录

一、向量

1.1初始化

1.2二范数

1.3点积

1.4叉积

二、矩阵

2.1单位矩阵

2.2矩阵的迹

2.3转置

2.4块操作

2.5乘法

2.6求逆

2.7特征值

2.8特征向量

三、四元数 

3.1初始化

3.2旋转矩阵

四、调试技巧 

4.1向量的调试

4.2矩阵的调试

五、整体代码 


 

通过官网下载,然后解压到自己指定的目录即可。在进行VS工程配置时,只需要如下图那样包含Eigen库所在目录即可。

右击工程名——》属性——》VC++目录——》常规——》包含目录

一、向量

常用的向量类型有 Vector3d Vector4d VectorXd VectorXcd等。其中VectorXd 表示实数向量,VectorXcd 表示复数向量,前者应用在许多科学计算和工程中,如物理模拟、信号处理等,后者在需要处理复数时应用,如电磁学、量子物理等。

1.1初始化

  1. Vector3d v3d_a = { 1,2,3 };
  2. cout << "Vector3d构造一:\n" << v3d_a << endl;
  3. Vector3d v3d_b;
  4. v3d_b << 4, 5, 6;
  5. cout << "Vector3d构造二:\n" << v3d_b << endl;

  1. Vector4d v4d = { 1.1,2.2,3.3,4.4 };
  2. cout << "Vector4d:\n" << v4d << endl;
  3. VectorXd vxd(8); //这里一定要指定向量长度,否则报错!
  4. vxd << 3, 1, 4, 1, 5, 9, 2, 6;
  5. cout << "VectorXd:\n" << vxd << endl;

  1. VectorXcd xcd(3, 1);
  2. xcd.setZero();
  3. xcd[0]._Val[0] = 1.2;
  4. xcd[2]._Val[1] = 1.3;
  5. cout << "VectorXcd:\n" << xcd << endl;
  6. cout << "VectorXcd real:\n" << xcd.real() << endl;

1.2二范数

  1. Vector3d v3d_a = { 1,2,3 };
  2. cout << "二范数:\n" << v3d_a.norm() << endl;

1.3点积

  1. Vector3d v3d_a = { 1,2,3 };
  2. Vector3d v3d_b;
  3. v3d_b << 4, 5, 6;
  4. cout << "点积:\n" << v3d_a.dot(v3d_b) << endl;

1.4叉积

  1. Vector3d v3d_a = { 1,2,3 };
  2. Vector3d v3d_b;
  3. v3d_b << 4, 5, 6;
  4. cout << "叉积:\n" << v3d_a.cross(v3d_b) << endl;

二、矩阵

2.1单位矩阵

  1. MatrixXd I = MatrixXd::Identity(4, 4);
  2. cout << "单位矩阵:\n" << I << endl;

2.2矩阵的迹

  1. MatrixXd MatA(3, 3);
  2. MatA << 1, 2, 3,
  3.         4, 5, 6,
  4.         7, 8, 9;
  5. cout << "矩阵的迹:\n" << MatA.trace() << endl;

2.3转置

cout << "矩阵的转置:\n" << MatA.transpose() << endl;

2.4块操作

大小为 (p,q), 起始于 (i,j)的块

动态大小的块表达式 matrix.block(i,j,p,q);

固定大小的块表达式matrix.block<p,q>(i,j);

二者区别是,固定大小的版本会在块比较小的时候快一点,但要求块大小在编译的时候就知道。

  1. MatrixXd MatB(3, 3);
  2. Vector3d va = { 0.1,0.4,0.7 };
  3. Vector3d vb = { 0.2,0.5,0.8 };
  4. Vector3d vc = { 0.3,0.6,0.9 };
  5. MatB.block<3, 1>(0, 0) = va; //固定 从0编码,以00为起点,存入31列的向量
  6. MatB.block(0, 1, 3, 1) = vb; //动态 从0编码,以01为起点,存入31列的向量
  7. MatB.block<3, 1>(0, 2) = vc;
  8. cout << "块操作:\n" << MatB << endl;

2.5乘法

cout << "矩阵乘法:\n" << MatA * MatB << endl;

2.6求逆

  1. MatrixXd MatC(3, 3);
  2. MatC << 1, 2, 3,
  3. 2, 5, 6,
  4. 3, 4, 8;
  5. cout << "矩阵求逆:\n" << MatC.inverse() << endl;

2.7特征值

  1. MatrixXd K(4, 4);
  2. K << -0.504129, 0.0190935, -0.836998, -0.137961,
  3. 0.0190935, -0.534845, 0.114843, -0.813407,
  4. -0.836998, 0.114843, 0.526649, -0.0167767,
  5. -0.137961, -0.813407, -0.0167767, 0.512325;
  6. VectorXd eigVals = K.eigenvalues().real();
  7. cout << "特征值:\n" << eigVals << endl;

2.8特征向量

  1. // 求解矩阵的最大特征值和对应特征向量
  2. EigenSolver<MatrixXd> es(K);
  3. MatrixXcd eigenvectors = es.eigenvectors();
  4. int index_of_max = MaxElementIndex(eigVals); // 找到最大特征值对应的下标
  5. VectorXcd max_eigenvector = eigenvectors.col(index_of_max);
  6. Vector4d vec4 = max_eigenvector.real();
  7. cout << "最大特征值对应的特征向量:\n" << vec4 << endl;

三、四元数 

3.1初始化

  1. Quaterniond q(4, 1, 2, 3);//要注意Eigen中四元数赋值的顺序,实数w在首;
  2. cout << "四元数:\n" << q << endl; //但是实际上它的内部存储顺序是[x y z w]
  3. cout << q.w() << " " << q.x() << " " << q.y() << " " << q.z() << endl; //单个取值

3.2旋转矩阵

  1. q = vec4;
  2. cout << "旋转矩阵:\n" << q.toRotationMatrix() << endl; //将四元数转换为旋转矩阵

四、调试技巧 

在用VS断点调试一般变量时,只需要鼠标悬停在变量上即可看见变量值,但由于矩阵和向量都是一个抽象对象,若要观察其具体变量就需要使用“快速监视“窗口,并且编辑表达式,使数据内容完全展开。

4.1向量的调试

双击选中变量

Shift+F9

一直展开到array,就可以看见向量全部内容

4.2矩阵的调试

同理,选中变量,Shift+F9,打开快速监视

此时展开到m_data变量,发现只能看到一个数值,这是因为该变量是个double指针类型

为了观察整个矩阵,在表达式栏,输入”,16”,表示展开指针后面16个数值,如下

敲击两次回车

认真比对存储顺序发现——矩阵元素存储按列依次排列,而非按行依次排列!

五、整体代码 

  1. #include <iostream>
  2. #include <Eigen/Core>
  3. #include <Eigen/Geometry>
  4. #include <Eigen/Eigenvalues>
  5. #include <Eigen/Dense>
  6. using namespace std;
  7. using namespace Eigen;
  8. int MaxElementIndex(VectorXd v)
  9. {
  10. int index = 0;
  11. for (int i = 1; i < v.size(); i++)
  12. {
  13. if (v(index) < v(i))
  14. {
  15. index = i;
  16. }
  17. }
  18. return index;
  19. }
  20. int main()
  21. {
  22. Vector3d v3d_a = { 1,2,3 };
  23. cout << "Vector3d构造一:\n" << v3d_a << endl;
  24. Vector3d v3d_b;
  25. v3d_b << 4, 5, 6;
  26. cout << "Vector3d构造二:\n" << v3d_b << endl;
  27. cout << "二范数:\n" << v3d_a.norm() << endl;
  28. cout << "点积:\n" << v3d_a.dot(v3d_b) << endl;
  29. cout << "叉积:\n" << v3d_a.cross(v3d_b) << endl;
  30. Vector4d v4d = { 1.1,2.2,3.3,4.4 };
  31. cout << "Vector4d:\n" << v4d << endl;
  32. VectorXd vxd(8); //这里一定要指定向量长度,否则报错!
  33. vxd << 3, 1, 4, 1, 5, 9, 2, 6;
  34. cout << "VectorXd:\n" << vxd << endl;
  35. VectorXcd xcd(3, 1);
  36. xcd.setZero();
  37. xcd[0]._Val[0] = 1.2;
  38. xcd[2]._Val[1] = 1.3;
  39. cout << "VectorXcd:\n" << xcd << endl;
  40. cout << "VectorXcd real:\n" << xcd.real() << endl;
  41. MatrixXd I = MatrixXd::Identity(4, 4);
  42. cout << "单位矩阵:\n" << I << endl;
  43. MatrixXd MatA(3, 3);
  44. MatA << 1, 2, 3,
  45. 4, 5, 6,
  46. 7, 8, 9;
  47. cout << "矩阵的迹:\n" << MatA.trace() << endl;
  48. cout << "矩阵的转置:\n" << MatA.transpose() << endl;
  49. MatrixXd MatB(3, 3);
  50. Vector3d va = { 0.1,0.4,0.7 };
  51. Vector3d vb = { 0.2,0.5,0.8 };
  52. Vector3d vc = { 0.3,0.6,0.9 };
  53. MatB.block<3, 1>(0, 0) = va; //固定 从0编码,以00为起点,存入31列的向量
  54. MatB.block(0, 1, 3, 1) = vb; //动态 从0编码,以01为起点,存入31列的向量
  55. MatB.block<3, 1>(0, 2) = vc;
  56. cout << "块操作:\n" << MatB << endl;
  57. cout << "矩阵乘法:\n" << MatA * MatB << endl;
  58. MatrixXd MatC(3, 3);
  59. MatC << 1, 2, 3,
  60. 2, 5, 6,
  61. 3, 4, 8;
  62. cout << "矩阵求逆:\n" << MatC.inverse() << endl;
  63. MatrixXd K(4, 4);
  64. K << -0.504129, 0.0190935, -0.836998, -0.137961,
  65. 0.0190935, -0.534845, 0.114843, -0.813407,
  66. -0.836998, 0.114843, 0.526649, -0.0167767,
  67. -0.137961, -0.813407, -0.0167767, 0.512325;
  68. VectorXd eigVals = K.eigenvalues().real();
  69. cout << "特征值:\n" << eigVals << endl;
  70. // 求解矩阵的最大特征值和对应特征向量
  71. EigenSolver<MatrixXd> es(K);
  72. MatrixXcd eigenvectors = es.eigenvectors();
  73. int index_of_max = MaxElementIndex(eigVals); // 找到最大特征值对应的下标
  74. VectorXcd max_eigenvector = eigenvectors.col(index_of_max);
  75. Vector4d vec4 = max_eigenvector.real();
  76. cout << "最大特征值对应的特征向量:\n" << vec4 << endl;
  77. Quaterniond q(4, 1, 2, 3);//要注意Eigen中四元数赋值的顺序,实数w在首;
  78. cout << "四元数:\n" << q << endl; //但是实际上它的内部存储顺序是[x y z w]
  79. cout << q.w() << " " << q.x() << " " << q.y() << " " << q.z() << endl; //单个取值
  80. q = vec4;
  81. cout << "旋转矩阵:\n" << q.toRotationMatrix() << endl; //将四元数转换为旋转矩阵
  82. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/79248
推荐阅读
相关标签
  

闽ICP备14008679号