zl程序教程

您现在的位置是:首页 >  后端

当前栏目

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

C++numpyUbuntu 环境 简单 技巧 版本 线性代数
2023-09-14 09:15:32 时间

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