当前位置: 首页 > news >正文

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

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C++使用技巧(十):C++编译生成与调用自定义静态库/动态库
  • 张越:智慧要包括一种向善之心
  • C++使用技巧(十一):函数返回一个数组
  • 张越:每张脸背后都有故事
  • C++使用技巧(十三):Google-GTest测试框架的安装与使用(demo源码实现)
  • C++使用技巧(十四):ubuntu16.04--C++ (Cpp) PCM示例与pcm及音频算法的参考资料
  • 熊节:谁震撼了世界——第14届Jolt奖点评
  • C++使用技巧(十五):类构造函数 与 析构函数
  • 刘江:国外计算机图书月旦评(2004.4)
  • C++使用技巧(十六):智能指针
  • 聚合页面更新
  • C++使用技巧(十七):虚函数
  • C++使用技巧(十八):多肽
  • 关于“滚动的一天”潜在危险
  • C++使用技巧(十九):内存管理
  • docker容器内的网络抓包
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • JDK 6和JDK 7中的substring()方法
  • PHP 7 修改了什么呢 -- 2
  • Promise面试题2实现异步串行执行
  • Python socket服务器端、客户端传送信息
  • socket.io+express实现聊天室的思考(三)
  • Vue官网教程学习过程中值得记录的一些事情
  • Vue--数据传输
  • 番外篇1:在Windows环境下安装JDK
  • 悄悄地说一个bug
  • 通过npm或yarn自动生成vue组件
  • 运行时添加log4j2的appender
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • 不要一棍子打翻所有黑盒模型,其实可以让它们发挥作用 ...
  • #如何使用 Qt 5.6 在 Android 上启用 NFC
  • (02)Hive SQL编译成MapReduce任务的过程
  • (C++17) optional的使用
  • (C语言)字符分类函数
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (ros//EnvironmentVariables)ros环境变量
  • (二)PySpark3:SparkSQL编程
  • (附源码)php投票系统 毕业设计 121500
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (附源码)计算机毕业设计ssm电影分享网站
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (四)Linux Shell编程——输入输出重定向
  • (算法)求1到1亿间的质数或素数
  • (一)ClickHouse 中的 `MaterializedMySQL` 数据库引擎的使用方法、设置、特性和限制。
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模
  • (转)linux下的时间函数使用
  • (轉)JSON.stringify 语法实例讲解
  • ***监测系统的构建(chkrootkit )
  • *算法训练(leetcode)第四十天 | 647. 回文子串、516. 最长回文子序列
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .Net高阶异常处理第二篇~~ dump进阶之MiniDumpWriter