首页 关于
树枝想去撕裂天空 / 却只戳了几个微小的窟窿 / 它透出天外的光亮 / 人们把它叫做月亮和星星
目录

3. Array类型和coefficient-wise operation

本章介绍Eigen的Array类型。

3.1 Array类型

与为了代数运算而设计的Matrix类型不同的是,Array类型是一种通用的类型。 Array还提供了一种方便的coefficient-wise操作,这种操作可能不具有代数意义,例如加一个常量到Array的每个元素中

Array也是一种类型模板(class template),它具有和Matrix一样的参数,而且其中前三个参数是必须的,而后三个参数有默认值。 更多关于Array参数的说明,这里不在详细介绍可以参考Matrix的说明。

        Array<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime> 

对于一些常见的case,Eigen还定义了一些Array前缀的一维或者二维的数组类型。 我们约定ArrayNt为一维的数组,其中N和t分别描述了数组的大小和元素类型。 类似的约定ArrayNNt为二维数组。如下是一些例子:

        typedef Array<float,Dynamic,1> ArrayXf;
        typedef Array<float,3,1> Array3f;
        typedef Array<double,Dynamic,Dynamic> ArrayXXd;
        typedef Array<double,3,3> Array33d;

小括号"()"被重载用来访问数组中的特定元素,而"<<"则被用于comma-initializer或者打印数组。 关于comma-initializer我们会在后续章节中予以详细介绍。参考如下的例程:

        #include <iostream>
        #include <Eigen/Dense>

        using namespace Eigen;
        using namespace std;
        int main()
        {
            ArrayXXf  m(2,2);

            m(0,0) = 1.0; m(0,1) = 2.0;
            m(1,0) = 3.0; m(1,1) = m(0,1) + m(1,0);
            cout << m << endl << endl;

            m << 1.0,2.0,
               3.0,4.0;
            cout << m << endl;
        } 

3.2 Array的一些运算规则

对两个Array的加减运算和Matrix的操作是一样的,都是把相同位置上的元素分别运算。 而Array还支持"array + scalar"这样的加减运算,这种运算会把数组中的每个元素加上或者减去一个相同的数据。

关于乘法运算,Array也可以和一个标量(scalar)相乘,这种运算形式和矩阵数乘是一样的。 但是当两个相同大小的Array进行乘法运算,则与加减法一样直接把相同位置上的元素分别相乘,所以只有同行同列 的两个Array才可以相乘。 参考如下的例程:

        #include <iostream>
        #include <Eigen/Dense>

        using namespace Eigen;
        using namespace std;
        int main()
        {
            ArrayXXf a(3,3);
            ArrayXXf b(3,3);
            a << 1,2,3,
               4,5,6,
               7,8,9;
            b << 1,2,3,
               1,2,3,
               1,2,3;
               
            cout << "a + b = " << endl << a + b << endl << endl;
            cout << "a - 2 = " << endl << a - 2 << endl << endl;
            cout << "a * b = " << endl << a * 2 << endl;
        } 

输出结果如下:

    a + b = 
     2  4  6
     5  7  9
     8 10 12

    a - 2 = 
    -1  0  1
     2  3  4
     5  6  7

    a * b = 
     2  4  6
     8 10 12
    14 16 18

除了上述的加减法和乘法外,Eigen还定义了一些其它的Array运算。例如.abs()被用来计算每个元素的绝对值; .sqrt()用于求取每个元素的平方根;而.min()可以用来求两个Array对应位置上的最小值。 参考如下例程,更多的Coefficient-wise运算以后会具体介绍。

        #include <iostream>
        #include <Eigen/Dense>

        using namespace Eigen;
        using namespace std;
        int main()
        {
            ArrayXf a = ArrayXf::Random(5);
            a *= 2;
            cout << "a =" << endl 
               << a << endl;
            cout << "a.abs() =" << endl 
               << a.abs() << endl;
            cout << "a.abs().sqrt() =" << endl 
               << a.abs().sqrt() << endl;
            cout << "a.min(a.abs().sqrt()) =" << endl 
               << a.min(a.abs().sqrt()) << endl;
        } 

输出结果如下:

    a =
      1.36
    -0.422
      1.13
      1.19
      1.65
    a.abs() =
     1.36
    0.422
     1.13
     1.19
     1.65
    a.abs().sqrt() =
    1.17
    0.65
    1.06
    1.09
    1.28
    a.min(a.abs().sqrt()) =
      1.17
    -0.422
      1.06
      1.09
      1.28

3.3 Array与Matrix之间的相互转换

Matrix是针对线性代数运算(linear algebraic operation)设计的,而Array是针对Coefficient-wise operation设计的。 在一些情况下,我们需要混合两种运算。为此,Eigen为Matrix提供了.array()方法将之转换为Array类型, 相应的为Array提供了.matrix()方法。

虽然.array()和.matrix()的返回值既可以做左值又可以做右值。但是Eigen禁止在一个表达式中同时出现Array和Matrix, 即像'+'这样的运算的左右两个值必须同时为Array或者Matrix。 不过Eigen是允许把一个Array(Matrix)的表达式的结果赋值给一个Matrix(Array)变量。

如下是一个Array和Matrix相互转换的例程,其中涉及到的.cwiseProduct()函数提供了一种在表达式中混合两种类型的方法。

        #include <iostream>
        #include <Eigen/Dense>

        using namespace Eigen;
        using namespace std;
        int main()
        {
          MatrixXf m(2,2);
          MatrixXf n(2,2);
          MatrixXf result(2,2);
          m << 1,2,
               3,4;
          n << 5,6,
               7,8;
          result = m * n;
          cout << "-- Matrix m*n: --" << endl << result << endl << endl;
          result = m.array() * n.array();
          cout << "-- Array m*n: --" << endl << result << endl << endl;
          result = m.cwiseProduct(n);
          cout << "-- With cwiseProduct: --" << endl << result << endl << endl;
          result = m.array() + 4;
          cout << "-- Array m + 4: --" << endl << result << endl << endl;
          result = (m.array() + 4).matrix() * m;
          cout << "-- Combination 1: --" << endl << result << endl << endl;
          result = (m.array() * n.array()).matrix() * m;
          cout << "-- Combination 2: --" << endl << result << endl << endl;
        } 

输出结果如下:

    -- Matrix m*n: --
    19 22
    43 50

    -- Array m*n: --
     5 12
    21 32

    -- With cwiseProduct: --
     5 12
    21 32

    -- Array m + 4: --
    5 6
    7 8
    
    -- Combination 1: --
    23 34
    31 46

    -- Combination 2: --
     41  58
    117 170



Copyright @ 高乙超. All Rights Reserved. 京ICP备16033081号-1