> 文章列表 > [Eigen中文文档] 高级初始化

[Eigen中文文档] 高级初始化

[Eigen中文文档] 高级初始化

文档总目录

本文目录

英文原文(Advanced initialization)

本文介绍了几种用于初始化矩阵的高级方法。提供了有关之前介绍的逗号初始化程序的更多详细信息。还解释了如何获得特殊矩阵,例如单位矩阵和零矩阵。

逗号初始化

Eigen提供了一个逗号初始化语法,这让用户可以很容易的设置矩阵、向量、数组的系数。仅仅需要简单的列出系数,从左上角开始,从左到右,从上到下依次列出系数。初始化对象的大小需要提前指定,如果给的系数太多或太少,Eigen会报错,如下:

Matrix3f m;
m << 1, 2, 3,4, 5, 6,7, 8, 9;
std::cout << m;

输出:

1 2 3
4 5 6
7 8 9

此外,初始化列表的元素本身可以是向量或者矩阵。逗号就是把向量和矩阵连接起来。例如,下面是在指定向量大小后,连接两个向量(注意,必须先设置大小,然后才能使用逗号初始化)。

RowVectorXd vec1(3);
vec1 << 1, 2, 3;
std::cout << "vec1 = " << vec1 << std::endl;RowVectorXd vec2(4);
vec2 << 1, 4, 9, 16;
std::cout << "vec2 = " << vec2 << std::endl;RowVectorXd joined(7);
joined << vec1, vec2;
std::cout << "joined = " << joined << std::endl;

输出:

vec1 = 1 2 3
vec2 =  1  4  9 16
joined =  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;
std::cout << matB << std::endl;

输出:

  1   2 0.1 0.23   4 0.3 0.4
0.1 0.2   1   2
0.3 0.4   3   4

逗号初始化同样也可以填充块表达式如m.row(i),下面使用一个更加复杂的方式来实现第一个示例:

Matrix3f m;
m.row(0) << 1, 2, 3;
m.block(1,0,2,2) << 4, 5, 7, 8;
m.col(2).tail(2) << 6, 9;                   
std::cout << m;

输出:

1 2 3
4 5 6
7 8 9

特殊矩阵和数组

matrixarray类有如Zero()之类的静态方法,可用于将所有系数初始化为零。

共有三种重载,第一个重载不需要任何参数,仅可以用在固定大小的对象。如果想要一个动态大小的对象,需要指定大小。因此,第二个重载需要一个参数用来初始化一维动态对象。第三个重载,需要两个参数用来初始化二维对象的大小。所有的重载解释如下:

std::cout << "A fixed-size array:\\n";
Array33f a1 = Array33f::Zero();
std::cout << a1 << "\\n\\n";std::cout << "A one-dimensional dynamic-size array:\\n";
ArrayXf a2 = ArrayXf::Zero(3);
std::cout << a2 << "\\n\\n";std::cout << "A two-dimensional dynamic-size array:\\n";
ArrayXXf a3 = ArrayXXf::Zero(3, 4);
std::cout << a3 << "\\n";

输出:

A fixed-size array:
0 0 0
0 0 0
0 0 0A one-dimensional dynamic-size array:
0
0
0A two-dimensional dynamic-size array:
0 0 0 0
0 0 0 0
0 0 0 0

类似的,静态方法Constant(value)把所有系数都初始化为value。如果对象的大小需要指定,除了value参数还需要额外的参数,如 MatrixXd::Constant(rows, cols, value)

方法Random()用随机的数字填充矩阵或阵列。

使用Identity()获取单位矩阵,这只能用于matrix而不能用于vector,因为单位矩阵的概念是线性代数中的。

方法LinSpaced(size,low,high)只对向量和一维数组有效,它产生一个指定大小在lowhigh的等差数列。下面的例子解释LinSpaced(),打印一个表格,包含角度和弧度的对应值,以及他们的sincos值。

ArrayXXf table(10, 4);
table.col(0) = ArrayXf::LinSpaced(10, 0, 90);
table.col(1) = M_PI / 180 * table.col(0);
table.col(2) = table.col(1).sin();
table.col(3) = table.col(1).cos();
std::cout << "  Degrees   Radians      Sine    Cosine\\n";
std::cout << table << std::endl;

输出:

Degrees   Radians      Sine    Cosine0         0         0         110     0.175     0.174     0.98520     0.349     0.342      0.9430     0.524       0.5     0.86640     0.698     0.643     0.76650     0.873     0.766     0.64360      1.05     0.866       0.570      1.22      0.94     0.34280       1.4     0.985     0.17490      1.57         1 -4.37e-08

此示例表明可以将像 LinSpaced() 这样的对象分配给变量(或表达式)。Eigen定义了诸如 setZero()、MatrixBase::setIdentity() 和 DenseBase::setLinSpaced() 之类的函数来执行此操作。下面的例子对比了三种方法来构造矩阵 J=[OIIO]J = \\begin{bmatrix} O & I \\\\ I & O \\\\ \\end{bmatrix}J=[OIIO]

const int size = 6;
MatrixXd mat1(size, size);
mat1.topLeftCorner(size/2, size/2)     = MatrixXd::Zero(size/2, size/2);
mat1.topRightCorner(size/2, size/2)    = MatrixXd::Identity(size/2, size/2);
mat1.bottomLeftCorner(size/2, size/2)  = MatrixXd::Identity(size/2, size/2);
mat1.bottomRightCorner(size/2, size/2) = MatrixXd::Zero(size/2, size/2);
std::cout << mat1 << std::endl << std::endl;MatrixXd mat2(size, size);
mat2.topLeftCorner(size/2, size/2).setZero();
mat2.topRightCorner(size/2, size/2).setIdentity();
mat2.bottomLeftCorner(size/2, size/2).setIdentity();
mat2.bottomRightCorner(size/2, size/2).setZero();
std::cout << mat2 << std::endl << std::endl;MatrixXd mat3(size, size);
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);
std::cout << mat3 << std::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 00 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 00 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

可以在 快速参考指南 中找到所有预定义矩阵、向量和数组对象的摘要。

用作临时对象

如上所示,Zero()Constant() 等静态方法可以在声明时或在赋值符右侧初始化变量。可以认为这些方法返回一个矩阵或数组,实际上,它们返回所谓的表达式对象,该对象在需要的时候才被计算,所以这样的语法不会产生任何额外开销。

这些表达式也可以用作临时对象。如下是 [入门](# 入门) 章节的第二个示例,其说明了这个特性:

#include <iostream>
#include <Eigen/Dense>using Eigen::MatrixXd;
using Eigen::VectorXd;int main()
{MatrixXd m = MatrixXd::Random(3,3);m = (m + MatrixXd::Constant(3,3,1.2)) * 50;std::cout << "m =" << std::endl << m << std::endl;VectorXd v(3);v << 1, 2, 3;std::cout << "m * v =" << std::endl << m * v << std::endl;
}

输出:

m =94 89.8 43.5
49.4  101 86.8
88.3 29.8 37.8
m * v =
404
512
261

表达式 m + MatrixXf::Constant(3,3,1.2) 构造了一个 3*3 的矩阵,其元素全为1.2+m

逗号初始化也可以构造临时对象,下面的例子构造了一个2*3的随机矩阵,然后与矩阵 [0110]\\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\\\ \\end{bmatrix}[0110] 相乘。

MatrixXf mat = MatrixXf::Random(2, 3);
std::cout << mat << std::endl << std::endl;
mat = (MatrixXf(2,2) << 0, 1, 1, 0).finished() * mat;
std::cout << mat << std::endl;

输出:

 0.68  0.566  0.823
-0.211  0.597 -0.605-0.211  0.597 -0.6050.68  0.566  0.823

在完成临时子矩阵的逗号初始化之后,这里需要使用finished()方法来获得实际的矩阵对象。