Eigen库学习 ---- 5.高级初始化操作
上篇为:Eigen库学习 ---- 4.块操作
本篇为这个链接的学习笔记。
介绍初始化矩阵的几种高级方法,介绍如何得到单位矩阵和零矩阵等特殊矩阵。
一、逗号初始化
Eigen提供了逗号初始化的方法,可以很容易的设置矩阵、向量或者数组的元素值。按照从左到右从上到下的顺序列出所有的元素。对象的大小需要事先指定,如果列出的元素个数太多或者太少,Eigen会报错。
例如:
Matrix3f m;
m << 1, 2, 3,
4, 5, 6,
7, 8, 9;
cout << m;
输出结果如下;
1 2 3
4 5 6
7 8 9
此外,初始化列表的元素本身可以是向量或者矩阵。常用的方法是将向量或者矩阵连接在一起。必须要设置大小,然后才能用逗号初始值设定。
例如:
RowVectorXd vec1(3);
vec1 << 1,2,3;
cout << "vec1=" << vec1 << endl;
RowVectorXd vec2(4);
vec2 << 1,4,9,16;
cout << "vec2=" << vec2 << endl;
RowVectorXd vec3(7);
vec3 << vec1, vec2;
cout << "vec3=" << vec3 << endl;
输出结果如下:
vec1=1 2 3
vec2= 1 4 9 16
vec3= 1 2 3 1 4 9 16
可以用相同的方法用矩阵块初始化矩阵,例如:
MatrixXf matA(2, 2);
matA << 1,2,3,4;
MatrixXf matB(4, 4);
matB << matA, matA / 10, matA / 10, matA;
cout << matB << endl;
输出结果如下:
1 2 0.1 0.2
3 4 0.3 0.4
0.1 0.2 1 2
0.3 0.4 3 4
逗号初始值设定项也可用于填充块表达式,如m.row(i)。下面是一个更复杂的方法来获得与上面第一个示例相同的结果:
Matrix3f m;
//第0行输入1,2,3
m.row(0) << 1, 2, 3;
//从1行0列的元素开始选择2x2的矩阵块,输入4,5,7,8
m.block(1, 0, 2, 2) << 4, 5, 7, 8;
//第2列的最后两个元素输入6,9
m.col(2).tail(2) << 6, 9;
cout << m;
输出结果如下:
1 2 3
4 5 6
7 8 9
二、特殊矩阵和数组
矩阵和数组类有静态方法,如Zero(),可用于将所有系数初始化为零。有三种变体。分别需要0个、1个、2个参数。
第一个变体不带参数,只能用于固定大小的对象。如果要将动态大小对象初始化为零,则需要指定大小。
第二个变体量需要一个参数,可以用于一维动态大小对象。
第三个变体需要两个参数,可以用于二维对象。
以下示例中说明了所有三种变体:
cout << "固定大小的数组:\n";
Array33f a1 = Array33f::Zero();
cout << a1 << "\n\n";
cout << "一维动态数组:\n";
ArrayXf a2 = ArrayXf::Zero(3);
cout << a2 << "\n\n";
cout << "二维动态数组:\n";
ArrayXXf a3 = ArrayXXf::Zero(3, 4);
cout << a3 << "\n";
输出结果如下:
固定大小的数组:
0 0 0
0 0 0
0 0 0
一维动态数组:
0
0
0
二维动态数组:
0 0 0 0
0 0 0 0
0 0 0 0
类似地,Constant(value)将所有系数设置为value。如果需要指定对象的大小,那么其他参数将放在value参数之前,如matrixXd::Constant(rows,cols,value)中所示。
方法Random()用随机系数填充矩阵或数组。
方法identity()可以得到单位矩阵;这种方法只适用于矩阵,不适用于数组,因为“单位矩阵”是一个线性代数概念。
方法LinSpaced(size,low,high)方法仅适用于向量和一维数组;它产生一个指定大小的向量,其系数在low和high之间等距(size)分布。
下面的示例演示了LinSpaced()方法,它打印一个表,其中以度表示角度,以弧度表示相应的角度,以及它们的正弦和余弦。
ArrayXXf table(10, 4);
table.col(0) = ArrayXf::LinSpaced(10, 0, 90);
table.col(1) = 3.1415926 / 180 * table.col(0);
table.col(2) = table.col(1).sin();
table.col(3) = table.col(1).cos();
cout << " Degrees Radians Sine Cosine\n";
cout << table << endl;
输出结果如下:
Degrees Radians Sine Cosine
0 0 0 1
10 0.174533 0.173648 0.984808
20 0.349066 0.34202 0.939693
30 0.523599 0.5 0.866025
40 0.698132 0.642788 0.766044
50 0.872665 0.766044 0.642788
60 1.0472 0.866025 0.5
70 1.22173 0.939693 0.34202
80 1.39626 0.984808 0.173648
90 1.5708 1 -4.37114e-08
这个例子展示了LinSpaced()返回的对象可以分配给变量(和表达式)。Eigen定义了诸如setZero()、MatrixBase::setIdentity()和DenseBase::setLinSpaced()之类的实用函数来方便地实现这一点。下面的示例对比了构造矩阵J的三种方法:
1.使用静态方法和赋值
2.使用setXxx()方法。
3.使用静态方法和逗号初始值设定项
const int size = 6;
//第一种方法,使用静态方法赋值
MatrixXd mat1(size,size);
//左上角的3x3的矩阵块被赋值为零矩阵
mat1.topLeftCorner(size / 2, size / 2) = MatrixXd::Zero(size / 2, size / 2);
//右上角的3x3矩阵被赋值为单位矩阵
mat1.topRightCorner(size / 2, size / 2) = MatrixXd::Identity(size/ 2,size/ 2);
//左下角的3x3矩阵被赋值为单位矩阵
mat1.bottomLeftCorner(size / 2, size / 2) = MatrixXd::Identity(size / 2, size / 2);
//右下角的3x3矩阵被赋值为零矩阵
mat1.bottomRightCorner(size / 2, size / 2) = MatrixXd::Zero(size / 2, size / 2);
cout << mat1 << endl << endl;
//第二种方法,setXxx()方法
MatrixXd mat2(size, size);
//左上角的3x3的矩阵块被赋值为零矩阵
mat2.topLeftCorner(size / 2, size / 2).setZero();
//右上角的3x3矩阵被赋值为单位矩阵
mat2.topRightCorner(size / 2, size / 2).setIdentity();
//左下角的3x3矩阵被赋值为单位矩阵
mat2.bottomLeftCorner(size / 2, size / 2).setIdentity();
//右下角的3x3矩阵被赋值为零矩阵
mat2.bottomRightCorner(size / 2, size / 2).setZero();
cout << mat2 << endl << endl;
//第三种方法,使用静态方法和逗号初始化
MatrixXd mat3(size, size);
//左上角的3x3的矩阵块被赋值为零矩阵
//右上角的3x3矩阵被赋值为单位矩阵
//左下角的3x3矩阵被赋值为单位矩阵
//右下角的3x3矩阵被赋值为零矩阵
mat3 << MatrixXd::Zero(size / 2, size / 2), MatrixXd::Identity(size / 2, size / 2),
MatrixXd::Identity(size / 2, size / 2), MatrixXd::Zero(size / 2, size / 2);
cout << mat3 << endl << endl;
输出结果如下:
0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0
0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0
0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0
三、临时对象
矩阵可以作为临时变量使用,且不会产生任何开销。例如:
MatrixXd m(3, 3);
m << 1, 2, 3, 4, 5, 6, 7, 8, 9;
m = (m + MatrixXd::Constant(3, 3, 1.2) * 50);
cout << "m=" << endl << m << endl;
VectorXd v(3);
v << 1,2,3;
cout << "m*v" << endl << m * v << endl;
输出结果如下:
m=
61 62 63
64 65 66
67 68 69
m*v
374
392
410
逗号表达式也可以作为临时模板进行输入。例如:
MatrixXf mat = MatrixXf::Random(2, 3);
cout << mat << endl << endl;
mat = (MatrixXf(2, 2) << 0, 1, 1, 0).finished() * mat;
cout << mat << endl;
输出结果如下:
-0.997497 -0.613392 0.170019
0.127171 0.617481 -0.0402539
0.127171 0.617481 -0.0402539
-0.997497 -0.613392 0.170019
这里需要.finished()方法,以便在临时子矩阵的逗号初始化完成后获取实际的矩阵对象。