C++使用技巧(九):ubuntu环境下Eigen线性代数库的简单使用(C++版本的numpy库))

本文详细介绍了Eigen库的使用,包括矩阵的创建、操作、矩阵运算、特征值计算等,并提供了C++代码示例。通过示例展示了如何在程序中引入Eigen库进行矩阵乘法、转置、求逆等操作,同时也涵盖了动态矩阵和向量的使用。此外,还提到了Eigen的Map类在处理内存中的数组时的作用。
摘要由CSDN通过智能技术生成

Eigen是可以用来进行线性代数、矩阵、向量操作等运算的C++库,支持多平台。使用类似Matlab的方式操作矩阵,功能强大。
Eigen包含了绝大部分能用到的矩阵算法,同时提供许多第三方的接口。Eigen一个重要特点是采用源码的方式提供给用户使用,在使用时只需要包含Eigen的头文件即可进行使用。之所以采用这种方式,是因为Eigen采用模板方式实现,由于模板函数不支持分离编译,所以只能提供源码而不是动态库的方式供用户使用,因此非常轻量而易于跨平台。我们要做的就是把eigen头文件和代码放在一起就可以了。

源码库下载地址:http://eigen.tuxfamily.org/index.php?title=Main_Page
下载之后进行编译安装:

我安装的版本是eigen-3.4.0:

cd eigen-3.4.0
mkdir build
cd build
cmake ..
sudo make
sudo make instal

官方教程:http://eigen.tuxfamily.org/dox/modules.html
位置在当前程序的当前目录:
在这里插入图片描述
测试代码:

// A simple quickref for Eigen. Add anything that's missing.
// Main author: Keir Mierle

// #include "eigen/Eigen/Dense"  //git的库所在的当前路径
#include "/data/xx_cmake/build/_deps/eigen3-src/Eigen/Dense"
// git clone https://gitlab.com/libeigen/eigen.git
#include <iostream>

template <typename T>
static void matrix_mul_matrix(T* p1, int iRow1, int iCol1, T* p2, int iRow2, int iCol2, T* p3)
{
    if (iRow1 != iRow2) return;

    //列优先
    //Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> > map1(p1, iRow1, iCol1);
    //Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> > map2(p2, iRow2, iCol2);
    //Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> > map3(p3, iCol1, iCol2);

    //行优先
    Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > map1(p1, iRow1, iCol1);
    Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > map2(p2, iRow2, iCol2);
    Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > map3(p3, iCol1, iCol2);

    map3 = map1 * map2;
}

int main(int argc, char* argv[])
{
    //1. 矩阵的定义
    Eigen::MatrixXd m(2, 2);
    Eigen::Vector3d vec3d;
    Eigen::Vector4d vec4d(1.0, 2.0, 3.0, 4.0);

    //2. 动态矩阵、静态矩阵
    Eigen::MatrixXd matrixXd;
    Eigen::Matrix3d matrix3d;

    //3. 矩阵元素的访问
    m(0, 0) = 1;
    m(0, 1) = 2;
    m(1, 0) = m(0, 0) + 3; 
    m(1, 1) = m(0, 0) * m(0, 1);
    std::cout << m << std::endl << std::endl;

    //4. 设置矩阵的元素
    m << -1.5, 2.4,
        6.7, 2.0;
    std::cout << m << std::endl << std::endl;
    int row = 4;
    int col = 5;
    Eigen::MatrixXf matrixXf(row, col);
    matrixXf << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20;
    std::cout << matrixXf << std::endl << std::endl;
    matrixXf << Eigen::MatrixXf::Identity(row, col);
    std::cout << matrixXf << std::endl << std::endl;

    //5. 重置矩阵大小
    Eigen::MatrixXd matrixXd1(3, 3);
    m = matrixXd1;
    std::cout << m.rows() << "  " << m.cols() << std::endl << std::endl;

    //6. 矩阵运算
    m << 1, 2, 7,
        3, 4, 8,
        5, 6, 9;
    std::cout << m << std::endl;
    matrixXd1 = Eigen::Matrix3d::Random();
    m += matrixXd1;
    std::cout << m << std::endl << std::endl;
    m *= 2;
    std::cout << m << std::endl << std::endl;
    std::cout << -m << std::endl << std::endl;
    std::cout << m << std::endl << std::endl;

    //7. 求矩阵的转置、共轭矩阵、伴随矩阵
    std::cout << m.transpose() << std::endl << std::endl;
    std::cout << m.conjugate() << std::endl << std::endl;
    std::cout << m.adjoint() << std::endl << std::endl;
    std::cout << m << std::endl << std::endl;
    m.transposeInPlace();
    std::cout << m << std::endl << std::endl;

    //8. 矩阵相乘、矩阵向量相乘
    std::cout << m*m << std::endl << std::endl;
    vec3d = Eigen::Vector3d(1, 2, 3);
    std::cout << m * vec3d << std::endl << std::endl;
    std::cout << vec3d.transpose()*m << std::endl << std::endl;

    //9. 矩阵的块操作
    std::cout << m << std::endl << std::endl;
    std::cout << m.block(1, 1, 2, 2) << std::endl << std::endl;
    std::cout << m.block<1, 2>(0, 0) << std::endl << std::endl;
    std::cout << m.col(1) << std::endl << std::endl;
    std::cout << m.row(0) << std::endl << std::endl;

    //10. 向量的块操作
    Eigen::ArrayXf arrayXf(10);
    arrayXf << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
    std::cout << vec3d << std::endl << std::endl;
    std::cout << arrayXf << std::endl << std::endl;
    std::cout << arrayXf.head(5) << std::endl << std::endl;
    std::cout << arrayXf.tail(4) * 2 << std::endl << std::endl;

    //11. 求解矩阵的特征值和特征向量
    Eigen::Matrix2f matrix2f;
    matrix2f << 1, 2, 3, 4;
    Eigen::SelfAdjointEigenSolver<Eigen::Matrix2f> eigenSolver(matrix2f);
    if (eigenSolver.info() == Eigen::Success) {
        std::cout << eigenSolver.eigenvalues() << std::endl << std::endl;
        std::cout << eigenSolver.eigenvectors() << std::endl << std::endl;
    }

    //12. 类Map及动态矩阵的使用
    int array1[4] = { 1, 2, 3, 4 };
    int array2[4] = { 5, 6, 7, 8 };
    int array3[4] = { 0, 0, 0, 0};
    matrix_mul_matrix(array1, 2, 2, array2, 2, 2, array3);
    for (int i = 0; i < 4; i++)
        std::cout << array3[i] << std::endl;

    return 0;
}

执行结果:

g++ eig.cc -o hello
./hello 



1 2
4 2

-1.5  2.4
 6.7    2

 1  2  3  4  5
 6  7  8  9 10
11 12 13 14 15
16 17 18 19 20

1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0

3  3

1 2 7
3 4 8
5 6 9
1.68038 2.59688 6.67045
2.78877 4.82329 8.53646
 5.5662  5.3951 8.55555

3.36075 5.19376 13.3409
5.57753 9.64659 17.0729
11.1324 10.7902 17.1111

-3.36075 -5.19376 -13.3409
-5.57753 -9.64659 -17.0729
-11.1324 -10.7902 -17.1111

3.36075 5.19376 13.3409
5.57753 9.64659 17.0729
11.1324 10.7902 17.1111

3.36075 5.57753 11.1324
5.19376 9.64659 10.7902
13.3409 17.0729 17.1111

3.36075 5.19376 13.3409
5.57753 9.64659 17.0729
11.1324 10.7902 17.1111

3.36075 5.57753 11.1324
5.19376 9.64659 10.7902
13.3409 17.0729 17.1111

3.36075 5.19376 13.3409
5.57753 9.64659 17.0729
11.1324 10.7902 17.1111

3.36075 5.57753 11.1324
5.19376 9.64659 10.7902
13.3409 17.0729 17.1111

188.779 262.611 288.083
211.508 306.245  346.54
361.785 531.241 625.526

 47.913
56.8576
  98.82

53.7709 76.0895 84.0461

3.36075 5.57753 11.1324
5.19376 9.64659 10.7902
13.3409 17.0729 17.1111

9.64659 10.7902
17.0729 17.1111

3.36075 5.57753

5.57753
9.64659
17.0729

3.36075 5.57753 11.1324

1
2
3

 1
 2
 3
 4
 5
 6
 7
 8
 9
10

1
2
3
4
5

14
16
18
20

-0.854102
   5.8541

-0.850651 -0.525731
 0.525731 -0.850651

19
22
43
50

Eigen库除了能实现各种矩阵操作外,貌似还提供《数学分析》中的各种矩阵操作(包括L矩阵U矩阵)。目前这里使用到的还是简单的矩阵操作,如加减乘除,求行列式,转置,逆,这些基本操作只要:

// A simple quickref for Eigen. Add anything that's missing.
// Main author: Keir Mierle
#include "eigen/Eigen/Dense"
#include "eigen/Eigen/Eigen"  //git的库所在的当前路径
// #include "/data/xx_cmake/build/_deps/eigen3-src/Eigen/Dense"
// git clone https://gitlab.com/libeigen/eigen.git
#include <iostream>
using namespace std; 
#include <unistd.h>
using namespace Eigen;  
  
void foo(MatrixXf& m)  
{  
    Matrix3f m2=Matrix3f::Zero(3,3);  
    m2(0,0)=1;  
    m=m2;  
}  
int main()  
{  
    /* 定义,定义时默认没有初始化,必须自己初始化 */  
    MatrixXf m1(3,4);   //动态矩阵,建立3行4列。  
    MatrixXf m2(4,3);   //4行3列,依此类推。  
    MatrixXf m3(3,3);  
    Vector3f v1;        //若是静态数组,则不用指定行或者列  
    /* 初始化 */  
    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;  
      
    /* 元素的访问 */  
    v1[1] = 1;  
    m3(2,2) = 7;  
    cout<<"v1:\n"<<v1<<endl;  
    cout<<"m3:\n"<<m3<<endl;  
    /* 复制操作 */  
    VectorXf v2=v1;             //复制后,行数与列数和右边的v1相等,matrix也是一样,  
                                //也可以通过这种方式重置动态数组的行数与列数  
    cout<<"v2:\n"<<v2<<endl;  
  
    /* 矩阵操作,可以实现 + - * / 操作,同样可以实现连续操作(但是维数必须符合情况), 
    如m1,m2,m3维数相同,则可以m1 = m2 + m3 + m1; */  
    m3 = m1 * m2;  
    v2 += v1;  
    cout<<"m3:\n"<<m3<<endl;  
    cout<<"v2:\n"<<v2<<endl;  
    //m3 = m3.transpose();  这句出现错误,估计不能给自己赋值  
    cout<<"m3转置:\n"<<m3.transpose()<<endl;  
    cout<<"m3行列式:\n"<<m3.determinant()<<endl;  
    m3 = m3.inverse();  
    cout<<"m3求逆:\n"<<m3<<endl;  
  
        // system("pause");  //windows
    pause();   //ubuntu
  
    return 0;  
}

执行结果:

v1:
0
1
0
m3:
1 0 0
0 1 0
0 0 7
v2:
0
1
0
m3:
 2  1  1
 2 21  1
 1  1 64
v2:
0
2
0
m3转置:
 2  2  1
 1 21  1
 1  1 64
m3行列式:
2540
m3求逆:
     0.52874   -0.0248032  -0.00787402
       -0.05         0.05            0
 -0.00748031 -0.000393701     0.015748

注意:安装的eigen3接口可能不一样,需要添加eigen3接口,案例如下:

#include <iostream>
#include <eigen3/Eigen/Dense>

using namespace Eigen;
using namespace std;
int main()
{
	//Vector3d v(1, 0, 0);
	//Vector3d w(0, 1, 0);
	Eigen::Vector3d v;
	v(0) = 0;
	v(1) = 3;
	v(2) = 1;
	cout << "Here is the vector v:\n" << v << endl;
	Eigen::Vector3d w;
	w(0) = 1;
	w(1) = 2;
	w(2) = -1;
	cout << "Here is the vector w:\n" << w << endl;
	cout << "Dot product: " << v.dot(w) << endl;
	cout << "Cross product:\n" << v.cross(w) << endl;//向量v叉乘向量W为(-5,1,-3)
	cout << "Cross product:\n" << w.cross(v) << endl; //向量w叉乘向量v为(5,-1,3)
}

结果:

g++ test.cc -std=c++11 -lgtest -lpthread -o main && ./main
Here is the vector v:
0
3
1
Here is the vector w:
 1
 2
-1
Dot product: 5
Cross product:
-5
 1
-3
Cross product:
 5
-1
 3
#include <iostream>
#include <eigen3/Eigen/Dense>
//路径:/usr/local/include/eigen3/Eigen/src/Core/Matrix.h
// EIGEN_MAKE_TYPEDEFS_ALL_SIZES(int,                  i)
// EIGEN_MAKE_TYPEDEFS_ALL_SIZES(float,                f)
// EIGEN_MAKE_TYPEDEFS_ALL_SIZES(double,               d)
// EIGEN_MAKE_TYPEDEFS_ALL_SIZES(std::complex<float>,  cf)
// EIGEN_MAKE_TYPEDEFS_ALL_SIZES(std::complex<double>, cd)

//复数计算
using Waveform = Eigen::Matrix2Xcd;
using Waveform = Eigen::Matrix2Xcf;
//不同精度类型的矩阵
using Waveform = Eigen::Matrix2Xi;//整形
using Waveform = Eigen::Matrix2Xf;
using Waveform = Eigen::MatrixXd;
int main()
{
  Waveform 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 Map类
https://blog.csdn.net/caomin1hao/category_7898685.html
https://blog.csdn.net/fengbingchun/article/details/47378515
visual studio工具下使用Eigen:
https://blog.csdn.net/wangxue_1231/article/details/90256026
命名空间:
https://www.runoob.com/cplusplus/cpp-namespaces.html

C++矩阵处理库–Eigen初步使用:https://www.cnblogs.com/rainbow70626/p/8819080.html
Ubuntu系统下使用C++的Eigen库:https://blog.csdn.net/weixin_42754903/article/details/110922890
教程:https://blog.csdn.net/hongge_smile/article/details/107296658

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

源代码杀手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值