Eigen 学习文档: Array类 和元素操作

Eigen 学习文档: Array类 和元素操作

本节旨在提供有关如何使用Eigen的Array类的概述和解释。

Array类是什么?

Array类提供通用数组,而不是用于线性代数的Matrix类。此外,Array类提供了一种简单的方法来执行系数操作,这可能没有线性代数意义,例如向数组中的每个系数添加一个常数或将两个数组相乘。

数组类型

Array是一个类模板,其模板参数与Matrix相同与Matrix一样,前三个模板参数是必需的

Array<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>

最后三个模板参数是可选的。由于这与Matrix完全一样,这里不再赘述,仅参考Matrix 类

Eigen还为一些常见情况提供了 typedef,其方式类似于Matrix typedef但略有不同,因为“数组”一词用于一维和二维数组。我们采用 ArrayNt 形式的 typedef 代表一维数组的约定,其中 Nt 是大小和标量类型,如本节解释的Matrix typedef 中所示。对于二维数组,我们使用 ArrayNNt 形式的 typedef。下表是一些示例:

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

访问数组

括号运算符被重载以提供对数组系数的写入和读取访问,就像矩阵一样。此外,<<运算符可用于初始化数组(通过逗号初始化程序)或打印它们。

#include <Eigen/Dense>
#include <iostream>
 
int main()
{
  Eigen::ArrayXXf  m(2,2);
  
  // assign some values coefficient by coefficient
  m(0,0) = 1.0; m(0,1) = 2.0;
  m(1,0) = 3.0; m(1,1) = m(0,1) + m(1,0);
  
  // print values to standard output
  std::cout << m << std::endl << std::endl;
 
  // using the comma-initializer is also allowed
  m << 1.0,2.0,
       3.0,4.0;
     
  // print values to standard output
  std::cout << m << std::endl;
}

输出:

1 2
3 5

1 2
3 4

有关逗号初始化器的更多信息,请参阅高级初始化一节

加减

两个数组的相加和相减与矩阵相同。如果两个数组具有相同的大小,则该操作有效,并且加法或减法是按系数进行的。

数组还支持array + scalar将标量添加到数组中的每个系数的形式的表达式这提供了一个不能直接用于Matrix对象的功能

#include <Eigen/Dense>
#include <iostream>
 
int main()
{
  Eigen::ArrayXXf a(3,3);
  Eigen::ArrayXXf b(3,3);
  a << 1,2,3,
       4,5,6,
       7,8,9;
  b << 1,2,3,
       1,2,3,
       1,2,3;
       
  // Adding two arrays
  std::cout << "a + b = " << std::endl << a + b << std::endl << std::endl;
 
  // Subtracting a scalar from an array
  std::cout << "a - 2 = " << std::endl << a - 2 << std::endl;
}

输出:

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

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

乘法

首先,当然可以将一个数组乘以一个标量,这与矩阵的工作方式相同。

数组与矩阵的根本不同之处在于将两个数组相乘矩阵将乘法解释为矩阵乘积,而数组将乘法解释为系数乘积。因此,当且仅当它们具有相同的维度时,两个数组才能相乘

#include <Eigen/Dense>
#include <iostream>
 
int main()
{
  Eigen::ArrayXXf a(2,2);
  Eigen::ArrayXXf b(2,2);
  a << 1,2,
       3,4;
  b << 5,6,
       7,8;
  std::cout << "a * b = " << std::endl << a * b << std::endl;
}
# 输出:
a * b = 
 5 12
21 32

其他操作方法

除了上述的加法、减法和乘法运算符之外,Array类还定义了其他系数操作。例如,.abs()方法获取每个系数的绝对值,而.sqrt()计算系数的平方根

如果你有两个大小相同的数组,你可以调用.min(.)来构造一个数组其系数是两个给定数组的对应系数中的最小值。这些操作在以下示例中进行了说明。

#include <Eigen/Dense>
#include <iostream>
 
int main()
{
  Eigen::ArrayXf a = Eigen::ArrayXf::Random(5);
  a *= 2;
  std::cout << "a =" << std::endl
            << a << std::endl;
  std::cout << "a.abs() =" << std::endl
            << a.abs() << std::endl;
  std::cout << "a.abs().sqrt() =" << std::endl
            << a.abs().sqrt() << std::endl;
  std::cout << "a.min(a.abs().sqrt()) =" << std::endl
            << a.min(a.abs().sqrt()) << std::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

更多系数操作可以在快速参考指南中找到。

在数组和矩阵表达式之间转换

什么时候应该使用Matrix类的对象,什么时候应该使用Array类的对象?你不能对数组应用矩阵运算,也不能对矩阵应用数组运算。

因此,如果你需要进行线性代数运算,例如矩阵乘法,那么你应该使用矩阵;如果你需要进行系数操作,那么你应该使用数组

但是,有时并不是那么简单,而是需要同时使用Matrix和Array操作。在这种情况下,你需要将矩阵转换为数组或相反。无论选择将对象声明为数组还是矩阵,这都可以访问所有操作。

矩阵有一个.array()方法,可以将它们“转换”为数组,因此可以轻松应用系数运算。相反,数组中有一个.matrix()方法。与所有Eigen表达式抽象一样,这没有任何运行时成本(前提是你让编译器进行优化)。

.array ()和.matrix()都可以用作右值和左值

混用矩阵和数组在Eigen中是禁止。例如,你不能直接添加矩阵和数组;运算符的操作数+要么都是矩阵,要么都是数组。但是,使用.array()和.matrix()很容易从一个转换为另一个。此规则的例外是赋值运算符:允许将矩阵分配给数组变量,或者将数组分配给矩阵变量

以下示例显示了如何通过使用.array()方法对Matrix对象使用数组操作。例如,该语句采用两个矩阵和,将它们都转换为数组,用于将它们按系数相乘并将结果分配给矩阵变量(这是合法的,因为Eigen允许将数组表达式分配给矩阵变量)。result = m.array() * n.array()mnresult

事实上,这种用例非常普遍,以至于Eigen为矩阵提供了一个const .cwiseProduct(.)方法来计算系数乘积。这也显示在示例程序中。

#include <Eigen/Dense>
#include <iostream>
 
using Eigen::MatrixXf;
 
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;
  std::cout << "-- Matrix m*n: --\n" << result << "\n\n";
  result = m.array() * n.array();
  std::cout << "-- Array m*n: --\n" << result << "\n\n";
  result = m.cwiseProduct(n);
  std::cout << "-- With cwiseProduct: --\n" << result << "\n\n";
  result = m.array() + 4;
  std::cout << "-- Array m + 4: --\n" << result << "\n\n";
}
# 输出:
-- 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

类似地,如果array1array2是数组,则表达式array1.matrix() * array2.matrix()计算它们的矩阵乘积。

下面是一个更高级的示例

该表达式(m.array() + 4).matrix() * m将 4 与矩阵中的每个系数相加m,然后计算结果与 的矩阵乘积m。类似地,表达式(m.array() * n.array()).matrix() * m计算矩阵的系数乘积mn然后计算结果与 的矩阵乘积m

#include <Eigen/Dense>
#include <iostream>
 
using Eigen::MatrixXf;
 
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.array() + 4).matrix() * m;
  std::cout << "-- Combination 1: --\n" << result << "\n\n";
  result = (m.array() * n.array()).matrix() * m;
  std::cout << "-- Combination 2: --\n" << result << "\n\n";
}
# 输出:
-- Combination 1: --
23 34
31 46

-- Combination 2: --
 41  58
117 170

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值