Eigen教程(3)之矩阵和向量的运算

Eigen教程(3)之矩阵和向量的运算
转载于:
矩阵和向量的运算
提供⼀些概述和细节:关于矩阵、向量以及标量的运算。
介绍
Eigen提供了matrix/vector的运算操作,既包括重载了c++的算术运算符+/-/*,也引⼊了⼀些特殊的运算⽐如点乘dot、叉乘cross等。
对于Matrix类(matrix和vectors)这些操作只⽀持线性代数运算,⽐如:matrix1*matrix2表⽰矩阵的乘机,vetor+scalar是不允许的。如果你想执⾏⾮线性代数操作,请看下⼀篇(暂时放下)。
加减
左右两侧变量具有相同的尺⼨(⾏和列),并且元素类型相同(Eigen不⾃动转化类型)操作包括:
⼆元运算 + 如a+b
⼆元运算 - 如a-b
⼀元运算 - 如-a
复合运算 += 如a+=b
复合运算 -= 如a-=b
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
Matrix2d a;
a << 1, 2,
3, 4;
MatrixXd b(2,2);
b << 2, 3,
1, 4;
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(1,2,3);
Vector3d w(1,0,0);
std::cout << "-v + w - v =\n" << -v + w - v << std::endl;
}
输出:
a +
b =
3 5
4 8
a -
b =
-1 -1
2  0
Doing a += b;
Now a =
3 5
4 8
-v + w - v =
-1
-4
-6
标量乘法和除法
乘/除标量是⾮常简单的,如下:
钻采工艺
⼆元运算 * 如matrix*scalar
⼆元运算 * 如scalar*matrix
⼆元运算 / 如matrix/scalar
复合运算 *= 如matrix*=scalar
复合运算 /= 如matrix/=scalar
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
Matrix2d a;
a << 1, 2,
3, 4;
Vector3d v(1,2,3);
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 *= 2;
std::cout << "Now v =\n" << v << std::endl;
}
结果
a * 2.5 =
2.5  5
7.5  10
0.1 * v =
0.1
0.2
0.3
Doing v *= 2;
Now v =
2
4
6
表达式模板
这⾥简单介绍,在⾼级主题中会详细解释。在Eigen中,线性运算⽐如+不会对变量⾃⾝做任何操作,会返回⼀个“表达式对象”来描述被执⾏的计算。当整个表达式被评估完(⼀般是遇到=号),实际的操作才执⾏。
这样做主要是为了优化,⽐如
VectorXf a(50), b(50), c(50), d(50);
...
a = 3*
b + 4*
c + 5*d;
Eigen会编译这段代码最终遍历⼀次即可运算完成。
for(int i = 0; i < 50; ++i)
a[i] = 3*b[i] + 4*c[i] + 5*d[i];
因此,我们不必要担⼼⼤的线性表达式的运算效率。
转置和共轭
表⽰transpose转置
表⽰conjugate共轭
表⽰adjoint(共轭转置) 伴随矩阵
MatrixXcf a = MatrixXcf::Random(2,2);
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;
输出
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)
对于实数矩阵,conjugate不执⾏任何操作,adjoint等价于transpose。
transpose和adjoint会简单的返回⼀个代理对象并不对本省做转置。如果执⾏ anspose() ,a不变,转置结果被赋值给b。如果执
⾏ anspose() Eigen在转置结束之前结果会开始写⼊a,所以a的最终结果不⼀定等于a的转置。
Matrix2i a; a << 1, 2, 3, 4;
正丁醇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;
Here is the matrix a:
1 2
3 4
and the result of the aliasing effect:
1 2
2 4
这被称为“别名问题”。在debug模式,当assertions打开的情况加,这种常见陷阱可以被⾃动检测到。对 anspose() 这种操作,可以执⾏in-palce转置。类似还有adjointInPlace。
MatrixXf a(2,3); a << 1, 2, 3, 4, 5, 6;
电子科技大学学报cout << "Here is the initial matrix a:\n" << a << endl;
cout << "and after being transposed:\n" << a << endl;
Here is the initial matrix a:
1 2 3
4 5 6
and after being transposed:
1 4
2 5
3 6
矩阵-矩阵的乘法和矩阵-向量的乘法
向量也是⼀种矩阵,实质都是矩阵-矩阵的乘法。
⼆元运算 *如a*b
复合运算 *=如a*=b
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
ecms
Matrix2d mat;
mat << 1, 2,
3, 4;
Vector2d u(-1,1), v(2,0);
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" << anspose() << 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;
}
输出
Here is mat*mat:
7 10
15 22
Here is mat*u:华南热带作物学院
1
1
Here is u^T*mat:
2 2
Here is u^T*v:
-2
报告格式
Here is u*v^T:
-2 -0
2  0
Let's multiply mat by itself
Now mat is mat:
7 10
15 22
m=m*m并不会导致别名问题,Eigen在这⾥做了特殊处理,引⼊了临时变量。实质将编译为:
tmp = m*m
m = tmp
如果你确定矩阵乘法是安全的(并没有别名问题),你可以使⽤noalias()函数来避免临时变量 c.noalias() += a*b 。点运算和叉运算
dot()执⾏点积,cross()执⾏叉积,点运算得到1*1的矩阵。当然,点运算也可以⽤u.adjoint()*v来代替。
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
int main()
{
Vector3d v(1,2,3);
Vector3d w(0,1,2);
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;
}
输出
Dot product: 8
Dot product via a matrix product: 8
Cross product:
1
-
2
1
注意:点积只对三维vector有效。对于复数,Eigen的点积是第⼀个变量共轭和第⼆个变量的线性积。
基础的归约操作
Eigen提供了⽽⼀些归约函数:sum()、prod()、maxCoeff()和minCoeff(),他们对所有元素进⾏操作。

本文发布于:2024-09-22 04:38:54,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/65771.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:矩阵   运算   操作   转置   表达式   变量   乘法   结果
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议