1.2 矩阵和向量的运算

1.介绍

eigen给矩阵和向量的算术运算提供重载的c++算术运算符例如+,-,*或这一些点乘dot(),叉乘cross()等等。对于矩阵类(矩阵和向量,之后统称为矩阵

类),算术运算只重载线性代数的运算。例如matrix1*matrix2表示矩阵的乘法,同时向量+标量是不允许的!如果你想进行所有的数组算术运算,请看下

一节!

2.加减法

因为eigen库无法自动进行类型转换,因此矩阵类的加减法必须是两个同类型同维度的矩阵类相加减。

这些运算有:

双目运算符:+,a+b

双目运算符:-,a-b

单目运算符:-,-a

复合运算符:+=,a+=b

复合运算符:-=,a-=b

例子:

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
Matrix2d a;
a << , ,
, ;
MatrixXd b(,);
b << , ,
, ;
std::cout << "a + b =\n" << a + b << std::endl;
std::cout << "a - b =\n" << a - b << std::endl;
std::cout << "Doing a += b;" << std::endl;
a += b;
std::cout << "Now a =\n" << a << std::endl;
Vector3d v(,,);
Vector3d w(,,);
std::cout << "-v + w - v =\n" << -v + w - v << std::endl;
}

3.标量乘法和除法

标量的乘除法非常简单:

双目运算符:*,matrix*scalar

双目运算符:*,scalar*matrix

即乘法满足交换律

双目运算符:/,matrix/scalar

矩阵中的每一个元素除以标量

复合运算符:*=,matrix*=scalar

复合运算符:/=,matrix/=scalar

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
Matrix2d a;
a << , ,
, ;
Vector3d v(,,);
std::cout << "a * 2.5 =\n" << a * 2.5 << std::endl;
std::cout << "0.1 * v =\n" << 0.1 * v << std::endl;
std::cout << "Doing v *= 2;" << std::endl;
v *= ;
std::cout << "Now v =\n" << v << std::endl;
}
//output
a * 2.5 =
2.5
7.5
0.1 * v =
0.1
0.2
0.3
Doing v *= ;
Now v =

4.对表达式模板的注释

在eigen中,+号算术运算符不会通过自身函数执行任何计算,它们只是返回一个表达式,来描述计算的过程。实际的计算是在执行等号时,整个表达式开

始进行计算。

比如:

VectorXf a(), b(), c(), d();
...
a = *b + *c + *d;

eigen把它编译成一个循环,这样数组只执行依次运算,就像下列循环一样:

for(int i = ; i < ; ++i)
a[i] = *b[i] + *c[i] + *d[i];

因此,在eigen 中,你不必担心使用相当大的算术运算表达式,它会提供给eigen更多优化代码的机会。

5.转置和共轭

矩阵类的成员函数transpose(),conjugate(),adjoint(),分别对应矩阵的转置aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAUCAIAAAAcIrrpAAAB4klEQVR4nGP5//8/A/UACxXNIse4n1e6E/rfaQpfmzHjiU+BN+uFKyZTVyfKMpNp3H92/dIeF827xcsPu1fXp3OfO/BJjJl813Gouhkx/H995+JP1QARZmZuU2cRJFnywu7no1PPxcwVODAk8Br37UyFoWnnPec1L3YHCzMixP9/BjnOX5gZQwce4/4+Xjv1dUSoWNPxow9+BAtzojnOAovj8Bj35eTULbrF3WI3m1afuPLhnzEnE8RlX+/sWT5/66OvXkcuvpUxRnMhLuP+PFg+5VP8ZE3R+ybSDEsP3f0eL8kNlmDkVnFNmXIjBbs27Mb9/3h4wnaj3BXCjKz/rVSZJp49//qPDTcR0YZVye87iyZ/S56twQZk86iZyTJMO3Tne64CL1nG/X+3t3XimQviAXYdIO6vly8Zvlw++fSXC9h4Uo37dWPOhD/dZ88FikLC/sf5cg2j/sM3vzKQYdy/19taNhsU7oKaBQTs0gayDL9vABOLvyCWpIHXuB9Xpna9iVthgJTIGHkUdMQZjh6/9vG/IQcjA36AZNzf1/t78rI6LrKHbbwWnavHBRb8/WBVY+f+twz/37YV9ytOKrASYsJhErpxzKKO5cuvl6PKsyqEdW4I6yTgKGzGUQNQ2TgApZ25pLNQ2DUAAAAASUVORK5CYII=" alt="" name="对象1" width="26" height="20" hspace="8" />
,共轭aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAABa0lEQVR4nGP5//8/A7mAhWyd2DX/frCypnnbiz9IQox85qXdWdochDWzKoR3zg0Hsb6dqTA07bznvObFgmBhRqJshoG/j9dOfR0RKtZ0/OiDH8HCnKRo/nJy6hbd4m6xm02rT1z58M+Yk4lozX8eLJ/yKX6ypuh9E2mGpYfufo+X5CZS8/+PhydsN8pdIczI+t9KlWni2fOv/9hwY6jFqvn3nUWTvyXP1mADsnnUzGQZph268z1XgZcIzf/f7W2deOaCeIBdB4j76+VLhi+XTz795QI2DL/mXzfmTPjTffZcoCgkhH6cL9cw6j988ysDQc3/Xm9r2WxQuEsUHrbs0gayDL9vAKPLX5ADr+YfV6Z2vYlbYYAUqYw8CjriDEePX/v435CDEZfmv6/39+RldVxkD9t4LTpXjwss+PvBqsbO/W8Z/r9tK+5XnFRgJcSEVTOzqGP58uvlqE5hVQjr3BDWyYAVUDtX0UkzAN6PjRnhvV9lAAAAAElFTkSuQmCC" alt="" name="对象2" width="20" height="18" hspace="8" />
,共轭转置矩阵aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAUCAIAAAAcIrrpAAAB0klEQVR4nGP5//8/A/UACxXNGhTG/X19cMk55Sh3GdYft9ev/uQcY8zHSIFxzML6qhdKm36lauyd/yW1l5cRSY4czzIJWBUW7jd3npd9cqc2F7Jp+I37dqbC0LTznvOaF7uDhRHa/r090DWBoWdX1o7mKef68o2Q3IfHuL+P1059HREq1nT86IMfwcKccPF3N17Zt1TYijHbVm/fcOezoSExYffl5NQtusXdYjebVp+48uGfMScTVIJZxDrMFsxiU/AMU0DRhMu4Pw+WT/kUP1lT9L6JNMPSQ3e/x0ty4/YIAeP+fzw8YbtR7gphRtb/VqpME8+ef/3HhpuIaMOq5PedRZO/Jc/WYAOyedTMZBmmHbrzPVeBlyzj/r/b2zrxzAXxALsOEPfXy5cMXy6ffPrLBWw8qcb9ujFnwp/us+cCRSFh/+N8uYZR/+GbXxnIMO7f620tmw0Kd4nC4pGBXdpAluH3DWBi8RfkING4H1emdr2JW2HAiRBi5FHQEWc4evzax/+GHIwM+AGScX9f7+/Jy+q4yB628Vp0rh4XWPD3g1WNnfvfMvx/21bcrzipwEqICYdJ6MYxizqWL79ejirPqhDWuSGsk4CjsBlHDUBl4wCoCq4pvXDklgAAAABJRU5ErkJggg==" alt="" name="对象3" width="26" height="20" hspace="8" />
,特此说明adjoint()并不表示伴随矩

阵,而是共轭转置矩阵!!!!

例子:

MatrixXcf a = MatrixXcf::Random(,);//生成随机的复数类型矩阵
cout << "Here is the matrix a\n" << a << endl;
cout << "Here is the matrix a^T\n" << a.transpose() << endl;
cout << "Here is the conjugate of a\n" << a.conjugate() << endl;
cout << "Here is the matrix a^*\n" << a.adjoint() << endl;
//output
Here is the matrix a
(-0.211,0.68) (-0.605,0.823)
(0.597,0.566) (0.536,-0.33)
Here is the matrix a^T
(-0.211,0.68) (0.597,0.566)
(-0.605,0.823) (0.536,-0.33)
Here is the conjugate of a
(-0.211,-0.68) (-0.605,-0.823)
(0.597,-0.566) (0.536,0.33)
Here is the matrix a^*
(-0.211,-0.68) (0.597,-0.566)
(-0.605,-0.823) (0.536,0.33)

对于实矩阵,是没有共轭矩阵的,同时它的共轭转置矩阵(adjoint())等于它的转置(transpose()).

对于基本的算术运算,转置和共轭转置函数返回的是矩阵的引用,而不会实际转换矩阵对象。如果你对b做b=a.transpose(),这个将在求转置矩阵的同时,

将结果赋值给b。但是如果将a=a.transpose(),eigen将会在计算a的转置完成之前开始赋值结果给a,因此,这样的赋值将不会将a替换成它的转置,而是:

Matrix2i a; a << , , , ;
cout << "Here is the matrix a:\n" << a << endl;
a = a.transpose(); // !!! do NOT do this !!! cout << "and the result of the aliasing effect:\n" << a << endl;
//output
Here is the matrix a: and the result of the aliasing effect:

结果不再是a的转置,而是发生了混叠(aliasing issue).在调试模式中,在到达断点之前,这样的错误很容易被检测到。

为了将a替换为a的转置矩阵,可以使用transposeInPlace()函数:

MatrixXf a(,); a << , , , , , ;
cout << "Here is the initial matrix a:\n" << a << endl;
a.transposeInPlace();
cout << "and after being transposed:\n" << a << endl;
//output
Here is the initial matrix a: and after being transposed:

同样地,对于共轭转置矩阵(adjoint())也有类似的成员函数(adjointInPlace()).

6.矩阵-矩阵乘法和矩阵-向量乘法

矩阵乘法使用*运算符;

双目运算符:a*b

复合运算符:a*=b

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
Matrix2d mat;
mat << , ,
, ;
Vector2d u(-,), v(,);
std::cout << "Here is mat*mat:\n" << mat*mat << std::endl;
std::cout << "Here is mat*u:\n" << mat*u << std::endl;
std::cout << "Here is u^T*mat:\n" << u.transpose()*mat << std::endl;
std::cout << "Here is u^T*v:\n" << u.transpose()*v << std::endl;
std::cout << "Here is u*v^T:\n" << u*v.transpose() << std::endl;
std::cout << "Let's multiply mat by itself" << std::endl;
mat = mat*mat;
std::cout << "Now mat is mat:\n" << mat << std::endl;
}
//output
Here is mat*mat: Here is mat*u: Here is u^T*mat: Here is u^T*v:
-
Here is u*v^T:
- - Let's multiply mat by itself
Now mat is mat:

说明,前述表达式m=m*m可能会引起混叠的问题,但是对于矩阵乘法而言,不必担心:eigen将矩阵的乘法看作一种特殊的情况,它引入一个临时变量,

因此它将编译成以下代码:

tmp = m*m;
m = tmp;

如果你想让矩阵乘法安全的进行计算而没有混叠问题,你可以使用noalias()成员函数来避免临时变量的问题,例如:

c.noalias() += a * b; 

7.点乘和叉乘

点乘dot(),叉乘cross().点乘也可以使用u.adjoint()*v。

例子:

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
int main()
{
Vector3d v(,,);
Vector3d w(,,);
cout << "Dot product: " << v.dot(w) << endl;//点乘
double dp = v.adjoint()*w; // automatic conversion of the inner product to a scalar
cout << "Dot product via a matrix product: " << dp << endl;
cout << "Cross product:\n" << v.cross(w) << endl;//叉乘
}
//output
Dot product:
Dot product via a matrix product:
Cross product: -

注意:叉乘只能用于维数为3的向量,点乘使用于任何维数的向量。当使用复数时,第一个变量是共轭线性运算,第二个是线性运算。

8.基本的算术化简计算

eigen提供一些简化计算将给定的矩阵或向量编程单个值,比如对矩阵的所有元素求和sum(),求积prod(),求最大值maxCoeff()和求最小值

minCoeff():

#include <iostream>
#include <Eigen/Dense>
using namespace std;
int main()
{
Eigen::Matrix2d mat;
mat << , ,
, ;
cout << "Here is mat.sum(): " << mat.sum() << endl;//对矩阵所有元素求和
cout << "Here is mat.prod(): " << mat.prod() << endl;//对矩阵所有元素求积
cout << "Here is mat.mean(): " << mat.mean() << endl;//对矩阵所有元素求平均值
cout << "Here is mat.minCoeff(): " << mat.minCoeff() << endl;//取矩阵的元素最小值
cout << "Here is mat.maxCoeff(): " << mat.maxCoeff() << endl;//取矩阵元素的最大值
cout << "Here is mat.trace(): " << mat.trace() << endl;//取矩阵元素的迹
}
//output
Here is mat.sum():
Here is mat.prod():
Here is mat.mean(): 2.5
Here is mat.minCoeff():
Here is mat.maxCoeff():
Here is mat.trace():

矩阵的迹返回的是矩阵对角线元素的和,等价于a.diagonal().sum().

同时求最大值和最小值的函数可以接受引用的实参,来表示其最大最小值的行数和列数:

Matrix3f m = Matrix3f::Random();
std::ptrdiff_t i, j;//i,j是一个整型类型
float minOfM = m.minCoeff(&i,&j);//矩阵可以接受两个引用参数
cout << "Here is the matrix m:\n" << m << endl;
cout << "Its minimum coefficient (" << minOfM << ") is at position (" << i << "," << j << ")\n\n";//输出最小值所在行数列数
RowVector4i v = RowVector4i::Random();
int maxOfV = v.maxCoeff(&i);//向量只接受一个引用参数
cout << "Here is the vector v: " << v << endl;
cout << "Its maximum coefficient (" << maxOfV << ") is at position " << i << endl;//输出最大值所在列数
//output
Here is the matrix m:
0.68 0.597 -0.33
-0.211 0.823 0.536
0.566 -0.605 -0.444
Its minimum coefficient (-0.605) is at position (,)
Here is the vector v: -
Its maximum coefficient () is at position

9.运算的有效性

eigen库会检查你定义的运算。通常它在编译时检查并产生错误信息。这些错误信息可能很长很丑,但是eigen将重要信息用大写字母来显示出,例如:

Matrix3f m;
Vector4f v;
v = m*v; // Compile-time error: YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES

在许多情况下,当使用动态绑定矩阵时,编译器将不会在编译时检查,eigen将会在运行时检查,yejiuis说程序有可能因为不合法的运算而中断。

MatrixXf m(,);
VectorXf v();
v = m * v; // Run-time assertion failure here: "invalid matrix product"


1.2 eigen中矩阵和向量的运算的更多相关文章

  1. matlab中矩阵和向量的创建

    1.向量的创建 1)直接输入: 行向量:a=[1,2,3,4,5] 列向量:a=[1;2;3;4;5] 2)用“:”生成向量 a=J:K 生成的行向量是a=[J,J+1,…,K] a=J:D:K 生成 ...

  2. Eigen中的矩阵及向量运算

    Eigen中的矩阵及向量运算 ,[+,+=,-,-=] ,[\*,\*=] ,[.transpose()] ,[.dot(),.cross(),.adjoint()] ,针对矩阵元素进行的操作[.su ...

  3. 【神经网络与深度学习】【C/C++】比较OpenBLAS,Intel MKL和Eigen的矩阵相乘性能

    比较OpenBLAS,Intel MKL和Eigen的矩阵相乘性能 对于机器学习的很多问题来说,计算的瓶颈往往在于大规模以及频繁的矩阵运算,主要在于以下两方面: (Dense/Sparse) Matr ...

  4. numpy教程:矩阵matrix及其运算

    http://blog.csdn.net/pipisorry/article/details/48791403 numpy矩阵简介 NumPy函数库中存在两种不同的数据类型(矩阵matrix和数组ar ...

  5. DirectX11--HLSL中矩阵的内存布局和mul函数探讨

    前言 说实话,我感觉这是一个大坑,不知道为什么要设计成这样混乱的形式. 在我用的时候,以row_major矩阵,并且mul函数以向量左乘矩阵的形式来绘制时的确能够正常显示,并不会有什么感觉.但是也有人 ...

  6. Eigen使用矩阵作为函数参数

    1 使用矩阵作为函数参数介绍 文章来源Writing Functions Taking %Eigen Types as Parameters Eigen为了在函数中传递不同的类型使用了表达式模板技术. ...

  7. Eigen中的noalias(): 解决矩阵运算的混淆问题

    作者:@houkai本文为作者原创,转载请注明出处:http://www.cnblogs.com/houkai/p/6349990.html 目录 混淆例子解决混淆问题混淆和component级的操作 ...

  8. 从零单排入门机器学习:Octave/matlab的经常使用知识之矩阵和向量

    Octave/matlab的经常使用知识之矩阵和向量 之前一段时间在coursera看了Andrew ng的机器学习的课程,感觉还不错.算是入门了.这次打算以该课程的作业为主线,对机器学习基本知识做一 ...

  9. matlab 中使用 GPU 加速运算

    为了提高大规模数据处理的能力,matlab 的 GPU 并行计算,本质上是在 cuda 的基础上开发的 wrapper,也就是说 matlab 目前只支持 NVIDIA 的显卡. 1. GPU 硬件支 ...

随机推荐

  1. can't access lexical declaration `a' before initialization

    <script type="text/javascript"> alert(a); let a=2; </script> 以上代码报错:   Referen ...

  2. JVM内部细节之一:synchronized关键字及实现细节(轻量级锁Lightweight Locking)

    在C程序代码中我们可以利用操作系统提供的互斥锁来实现同步块的互斥访问及线程的阻塞及唤醒等工作.然而在Java中除了提供Lock API外还在语法层面上提供了synchronized关键字来实现互斥同步 ...

  3. springMVC的高级数据绑定,以及json交互,全局异常配置,

    一.窄化请求映射 1.在class上添加@RequestMapping(url)指定通用请求前缀, 限制此类下的所有方法请求url必须以请求前缀开头,通过此方法对url进行分类管理. 如下: @Con ...

  4. linux服务nfs与dhcp篇

    nfs复习: 1.简介:用于liunx与linux之间的文件传输系统 2.下载nfs-utils和rpcbind 3.打开配置文件/etc/exports——文件名(目录名)共享给予的ip地址(rw) ...

  5. Python · 进度条

    (这里是本章会用到的 GitHub 地址) 我实现的这个进度条可能是可以当做一个第三方库来使用的(这个人好自大,啧),它支持记录并发程序的进度且损耗基本只来源于 Python 本身 先来看看我们的进度 ...

  6. IntelliJ IDEA 中创建maven项目

    IDEA作为最好得开发工具之一集成了maven工具,今天记录一下我创建使用idea创建maven项目 1.双击IDEA图标,进入到如下界面,在该页面中,点击箭头所示的“Create New Proje ...

  7. 如何使用 Visual C# .NET 处理 Excel 事件

    事件处理概述 Visual C# .NET 使用委派处理来自组件对象模型 (COM) 服务器的事件.委派是 Microsoft Visual Studio .NET 中的一个新概念.对于 COM 事件 ...

  8. python大法好—模块 续

    1.sys模块 sys模块的常见函数列表 sys.argv: 实现从程序外部向程序传递参数. sys.exit([arg]): 程序中间的退出,arg=0为正常退出. sys.getdefaulten ...

  9. shell脚本可以解决的问题

    1.各类监控脚本,文件,内存,磁盘,端口 url 监控报警 2.监控网站目录文件是否被篡改,以及如何恢复 3.如何开发各类服务rsync nginx mysql等启动停止脚本 4.开发mysql主从复 ...

  10. leetcode617

    这道题想了很久,并没有掌握思想,写了很多,也没有解决.先贴出思考的过程. class Solution { public: vector<TreeNode> v1; vector<T ...