[Eigen中文文档] 切片和索引

news/2024/12/4 22:20:45/

专栏总目录

本文目录

      • 概述
      • 基本的切片
      • 编译时的大小和步长
      • 倒序
      • 索引序列
      • 自定义索引列表

英文原文(Slicing and Indexing)

本文介绍了如何使用操作运算符operator()索引行和列的子集。该 API 在 Eigen 3.4 中引入。它支持 block API 提供的所有功能。特别是,它支持切片,即获取一组行、列或元素,以及等间隔的从矩阵或者数组中提取元素。

概述

所有上述操作都是通过DenseBase::operator()(const RowIndices&, const ColIndices&)来完成的,每一个参数可以是:

  • 索引单行或列的整数,包括符号索引
  • 符号Eigen::all表示按递增顺序排列的所有行或列
  • Eigen::seq, Eigen::seqN或者 Eigen::placeholders::lastN 函数构造的算数序列
  • 任意一维整数向量、数组,形式如Eigen 向量数组表达式std::vectorstd::array 、 C的数组int[N]

更一般的,该函数可以接受任何有下列两个成员函数接口的对象

<integral type> operator[](<integral type>) const;
<integral type> size() const;

其中<integral type> 代表任何可以与Eigen::index兼容的整数,如std::ptrdiff_t

基本的切片

通过Eigen::seqEigen::seqN函数,取矩阵或向量中均匀间隔的一组行、列或元素,其中seq代表等差数列,用法如下:

方法描述示例
seq(firstIdx,lastIdx)返回从firstIdxlastIdx的整数序列seq(2,5) <=> {2,3,4,5}
seq(firstIdx,lastIdx,incr)同上,但是索引步长为incrseq(2,8,2) <=> {2,4,6,8}
seqN(firstIdx,size)firstIdx开始,索引步长1,总的个数为sizeseqN(2,5) <=> {2,3,4,5,6}
seqN(firstIdx,size,incr)同上,索引步长为incrseqN(2,3,3) <=> {2,5,8}

一旦等差数列通过operator()传递给它,firstIdxlastIdx参数也可以用Eigen::last符号来定义,该符号表示矩阵/向量的最后一行、最后一列或最后一个元素的索引,使用如下:

目的代码等价的块操作
包含从第i行到最后一行,从第0列开始,共n列的块A(seq(i,last), seqN(0,n))A.bottomLeftCorner(A.rows()-i,n)
包含从第i行到第m行,从第j列开始,共n列的块A(seqN(i,m), seqN(j,n))A.block(i,j,m,n)
包含从第i0行到第i1行,从第j0列到第j1列的块A(seq(i0,i1), seq(j0,j1)A.block(i0,j0,i1-i0+1,j1-j0+1)
A的偶数列A(all, seq(0,last,2))
A的前n个奇数行A(seqN(1,n,2), all)
倒数第二列A(all, last-1)A.col(A.cols()-2)
A的中间一行A(last/2,all)A.row((A.rows()-1)/2)
向量v从第i个元素到最后一个元素v(seq(i,last))v.tail(v.size()-i)
向量v的最后n个元素v(seq(last+1-n,last))v.tail(n)

示例如下:

// 代码索引 3-5-1-1
MatrixXi A = MatrixXi::Random(7, 6);
cout << "Initial matrix A:\n"<< A << "\n\n";// 包含从第i行到最后一行,从第0列开始,共n列的块(i: 2, n: 3)
cout << "A(seq(i,Eigen::last), seqN(0,n)): (i: 2, n: 3)\n"<< A(seq(2, Eigen::last), seqN(0, 3)) << "\n\n";// 包含从第i行到第m行,从第j列开始,共n列的块(i: 1, m: 2, j: 2, n: 4)
cout << "A(seq(i,m), seqN(j,n)): (i: 1, m: 2, j: 2, n: 4)\n"<< A(seqN(1, 2), seqN(2, 4)) << "\n\n";// 包含从第i0行到第i1行,从第j0列到第j1列的块(i0: 1, i1: 2, j0: 2, j1: 4)
cout << "A(seq(i0,i1), seq(j0,j1)): (i0: 1, i1: 2, j0: 2, j1: 4)\n"<< A(seq(1, 2), seq(2, 4)) << "\n\n";// A的偶数列
cout << "A的偶数列: \n"<< A(Eigen::all, seq(0, Eigen::last, 2)) << "\n\n";// A的前n个奇数行 (n: 3)
cout << "A的前n个奇数行: (n: 3)\n"<< A(seqN(1, 3, 2), Eigen::all) << "\n\n";// A的倒数第二列
cout << "A的倒数第二列: \n"<< A(Eigen::all, Eigen::last-1) << "\n\n";// A的中间一行
cout << "A的中间一行: \n"<< A(Eigen::last/2, Eigen::all) << "\n\n";Eigen::VectorXi v{{4,2,5,8,3}};
cout << "Initial vector v:\n"<< v << "\n\n";// 向量v从第i个元素到最后一个元素 (i: 2)
cout << "向量v从第i个元素到最后一个元素: (i: 2)\n"<< v(seq(2, Eigen::last)) << "\n\n";// 向量v最后n个元素
cout << "向量v最后n个元素: (n: 3)\n"<< v(seq(Eigen::last-3+1, Eigen::last)) << "\n\n";

输出如下:

Initial matrix A:730547559   576018668   971155939  -552146456  1071432243    52156343-226810938  -477225175   893772102  -779039257  -605038689   -13780431607950953   115899597   291438716   653214605    27772105  1015276632640895091   -48539462   466641602  -737276042   728237978  -445566813884005969   276748203  -769652652  -212720294   241892198   582736218-649503489  -290373134   229713912  -795018962  -438018766    57434405-353856438    28778235 -1038736613  -840076701   295391245   579635549A(seq(i,Eigen::last), seqN(0,n)): (i: 2, n: 3)607950953   115899597   291438716640895091   -48539462   466641602884005969   276748203  -769652652-649503489  -290373134   229713912-353856438    28778235 -1038736613A(seq(i,m), seqN(j,n)): (i: 1, m: 2, j: 2, n: 4)893772102 -779039257 -605038689  -13780431291438716  653214605   27772105 1015276632A(seq(i0,i1), seq(j0,j1)): (i0: 1, i1: 2, j0: 2, j1: 4)893772102 -779039257 -605038689291438716  653214605   27772105A的偶数列: 730547559   971155939  1071432243-226810938   893772102  -605038689607950953   291438716    27772105640895091   466641602   728237978884005969  -769652652   241892198-649503489   229713912  -438018766-353856438 -1038736613   295391245A的前n个奇数行: (n: 3)
-226810938 -477225175  893772102 -779039257 -605038689  -13780431640895091  -48539462  466641602 -737276042  728237978 -445566813
-649503489 -290373134  229713912 -795018962 -438018766   57434405A的倒数第二列: 
1071432243
-60503868927772105728237978241892198
-438018766295391245A的中间一行: 640895091  -48539462  466641602 -737276042  728237978 -445566813Initial vector v:
4
2
5
8
3向量v从第i个元素到最后一个元素: (i: 2)
5
8
3向量v最后n个元素: (n: 3)
5
8
3

正如在上一个示例中看到的,引用最后n个元素(或行/列)编写起来有点麻烦。使用非默认增量时,这将变得更加棘手和容易出错。因此,Eigen提供了Eigen::placeholders::lastN(size)Eigen::placeholders::lastN(size,incr)函数来完成最后几个元素的提取,用法如下:

Eigen官方建议使用Eigen::lastN(size)Eigen::lastN(size,incr)代替Eigen::placeholders::lastN(size)Eigen::placeholders::lastN(size,incr)

目的代码等价的块操作
向量v的最后n个元素v(lastN(n))v.tail(n)
A右下角m行n列的块A(lastN(m), lastN(n))A.bottomRightCorner(m,n)
A的最后n列,步长为mA(all, lastN(n,m))

示例如下:

Eigen::VectorXi v{{4,2,5,8,3}};
cout << "Initial vector v:\n"<< v << "\n\n";// Eigen提供最后几个元素的提取函数
// 向量v最后n个元素
cout << "向量v最后n个元素: (n: 3)\n"<< v(Eigen::lastN(3)) << "\n\n";MatrixXi A = MatrixXi::Random(7, 6);
cout << "Initial matrix A:\n"<< A << "\n\n";// A右下角m行n列的块
cout << "A右下角m行n列的块: (m: 3, n: 2)\n"<< A(Eigen::lastN(3), Eigen::lastN(2)) << "\n\n";// A的最后n列,步长为m
cout << "A的最后n列, 步长为m: (n: 3, m: 2)\n"<< A(Eigen::all, Eigen::lastN(3, 2)) << "\n\n";

输出如下:

Initial vector v:
4
2
5
8
3向量v最后n个元素: (n: 3)
5
8
3Initial matrix A:730547559   576018668   971155939  -552146456  1071432243    52156343-226810938  -477225175   893772102  -779039257  -605038689   -13780431607950953   115899597   291438716   653214605    27772105  1015276632640895091   -48539462   466641602  -737276042   728237978  -445566813884005969   276748203  -769652652  -212720294   241892198   582736218-649503489  -290373134   229713912  -795018962  -438018766    57434405-353856438    28778235 -1038736613  -840076701   295391245   579635549A右下角m行n列的块: (m: 3, n: 2)241892198  582736218
-438018766   57434405295391245  579635549A的最后n列, 步长为m: (n: 3, m: 2)576018668 -552146456   52156343
-477225175 -779039257  -13780431115899597  653214605 1015276632-48539462 -737276042 -445566813276748203 -212720294  582736218
-290373134 -795018962   5743440528778235 -840076701  579635549

编译时的大小和步长

在性能方面,Eigen和编译器可以利用编译时的大小和步长。为此,可以使用Eigen::fix<val>在编译时强制指定大小。而且,它可以和Eigen::last符号一起使用:

v(seq(last-fix<7>, last-fix<2>))

在这个示例中,Eigen在编译时就知道返回的表达式有6个元素。它等价于:

v(seqN(last-7, fix<6>))

我们可以访问A的偶数列,如:

A(all, seq(0,last,fix<2>))

倒序

也可以把步长设置为负数,按降序枚举行/列索引,例如,从第 20 列开始到第 10 列结束, 步长为-2

A(all, seq(20, 10, fix<-2>))

从最后一行开始,取n行:

A(seqN(last, n, fix<-1>), all)

也可以使用ArithmeticSequence::reverse() 方法来反转序列,前面的例子也可以写成:

A(lastN(n).reverse(), all)

索引序列

operator()输入的也可以是ArrayXi, std::vector<int>, std::array<int,N>等,如:

示例:

std::vector<int> ind{4,2,5,5,3};
MatrixXi A = MatrixXi::Random(4,6);
cout << "Initial matrix A:\n" << A << "\n\n";
cout << "A(all,ind):\n" << A(Eigen::placeholders::all,ind) << "\n\n";

输出如下:

Initial matrix A:7   9  -5  -3   3 -10-2  -6   1   0   5  -56  -3   0   9  -8  -86   6   3   9   2   6A(all,ind):3  -5 -10 -10  -35   1  -5  -5   0-8   0  -8  -8   92   3   6   6   9

也可以直接传递一个静态数组:

MatrixXi A = MatrixXi::Random(4,6);
cout << "Initial matrix A:\n" << A << "\n\n";
cout << "A(all,{4,2,5,5,3}):\n" << A(Eigen::placeholders::all,{4,2,5,5,3}) << "\n\n";

输出:

Initial matrix A:7   9  -5  -3   3 -10-2  -6   1   0   5  -56  -3   0   9  -8  -86   6   3   9   2   6A(all,{4,2,5,5,3}):3  -5 -10 -10  -35   1  -5  -5   0-8   0  -8  -8   92   3   6   6   9

也可以传递一个表达式:

ArrayXi ind(5); ind<<4,2,5,5,3;
MatrixXi A = MatrixXi::Random(4,6);
cout << "Initial matrix A:\n" << A << "\n\n";
cout << "A(all,ind-1):\n" << A(Eigen::placeholders::all,ind-1) << "\n\n";

输出:

Initial matrix A:7   9  -5  -3   3 -10-2  -6   1   0   5  -56  -3   0   9  -8  -86   6   3   9   2   6A(all,ind-1):
-3  9  3  3 -50 -6  5  5  19 -3 -8 -8  09  6  2  2  3

当传递一个具有编译时大小的对象(如Array4istd::array<int, N>或静态数组)时,返回的表达式也会显示编译时维度。

自定义索引列表

更一般的,operator()可以接受任何类型的对象:

Index s = ind.size(); or Index s = size(ind);
Index i;
i = ind[i];

这意味着可以构建自己的序列生成器并将其传递给operator()。下面是一个通过重复填充额外的第一行和列来扩大给定矩阵的示例:

struct pad {Index size() const { return out_size; }Index operator[] (Index i) const { return std::max<Index>(0,i-(out_size-in_size)); }Index in_size, out_size;
};Matrix3i A;
A.reshaped() = VectorXi::LinSpaced(9,1,9);
cout << "Initial matrix A:\n" << A << "\n\n";
MatrixXi B(5,5);
B = A(pad{3,5}, pad{3,5});
cout << "A(pad{3,N}, pad{3,N}):\n" << B << "\n\n";

输出:

Initial matrix A:
1 4 7
2 5 8
3 6 9A(pad{3,N}, pad{3,N}):
1 1 1 4 7
1 1 1 4 7
1 1 1 4 7
2 2 2 5 8
3 3 3 6 9

http://www.ppmy.cn/news/46838.html

相关文章

查询练习:条件加组筛选

查询 student 表中至少有 2 名男生的 class 。 -- 查看学生表信息 SELECT * FROM student; ---------------------------------------- | no | name | sex | birthday | class | ---------------------------------------- | 101 | 曾华 | 男 | 1977-09-01 | 95…

vue 动态组件

一见如故 // 一般配合<keep-alive>组件&#xff0c;避免反复重新渲染dom <keep-alive><component :is"com"></component> </keep-alive> <script> import Left from ./LeftComponent.vue import Right from ./RightComponent.v…

Ae:自动定向

Ae 菜单&#xff1a;图层/变换/自动定向 Auto-Orient 快捷键&#xff1a;Ctrl Alt O 自动定向 Auto-Orient是 Ae 图层中的一个附加的、隐藏实现&#xff08;不会在时间轴面板上更改属性的值&#xff09;的功能&#xff0c;它可以使得图层自动旋转或改变方向以朝向指定的运动路…

【Linux阅读笔记】LinuxC一站式编程1-程序基本概念与gdb调试

目录 程序基本概念配置开发环境第一个程序C 复习 gdb单步执行与跟踪断点观察点段错误 程序基本概念 使用 ubuntu22.0 作为演示环境&#xff08;vmware 虚拟机搭设&#xff09; 配置开发环境 配置完基础开发环境后&#xff0c;可以直接下载一个 vscode 作为初始 LDE 使用&#x…

机器学习 day03(成本函数,简化后的和一般情况下的成本函数)

1. 成本函数 平方误差成本函数是最通常用于线性回归的成本函数最终&#xff0c;我们要找到一组w和b&#xff0c;让j函数的值最小误差&#xff1a;ŷ - y 2. 简化后的平方误差成本函数&#xff0c;即b 0 当w 1时&#xff0c;f(x) x&#xff0c;J(1) 0 左侧为f(x)函数&am…

Python 图像处理实用指南:11~12

原文&#xff1a;Hands-On Image Processing with Python 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【ApacheCN 计算机视觉 译文集】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 当别人说你没有底线的时候&#xff0c;…

程序员 如何避免职场危机,打造自己稀缺性

你在职场上如何又脱颖而出 你唯一的办法就干嘛 找一找怎么才能构建我自己的稀缺性 我经过我 多年的工作和有观察的体验 化是什么呢 从技术迭代进步的角度来说 因为软件越来a p i化 个人的能力被解脱了 一定会向上下有延伸 因为当你做一块 以前是一年做下来时间只需要一个月 是一…

(一)Linux:自由、开放、灵活的操作系统内核

目录 一、Linux的发展史 二、linux的开源 三、目前的现状 四、企业应用现状 五、发行的版本 六、安装与使用 七、利用云服务器配置Linux环境 一、Linux的发展史 Linux是一款由林纳斯托瓦兹&#xff08;Linus Torvalds&#xff09;开发的操作系统内核&#xff0c;它的发布…