Eigen子矩阵操作(block)

    xiaoxiao2022-07-03  171

    文章目录

    1、子矩阵操作简介2、块操作的一般使用方法3、行子式和列子式4、边角子矩阵5、向量的子向量操作

    1、子矩阵操作简介

    子矩阵操作又称块操作,在矩阵运算中,子矩阵的提取和操作应用也十分广泛。因此Eigen中也提供了相关操作的方法。提取的子矩阵在操作过程中既可以用作左值也可以用作右值。

    2、块操作的一般使用方法

    在Eigen中最基本的快操作运算是用.block()完成的。提取的子矩阵同样分为动态大小和固定大小。

    块操作构建动态大小子矩阵提取块大小为(p,q),起始于(i,j)matrix.block(i,j,p,q)

    同样需要注意的是在Eigen中,索引是从0开始。所有的操作方法都可以适用于Array.同样使用固定大小的操作方式在小型矩阵运算时更加的快,但要求在编译时就要知道矩阵的大小。 下面是一个使用示例:

    #include <iostream> #include "Eigen/Dense" using namespace std; using namespace Eigen; int main() { MatrixXf m(4,4); m<< 1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16; cout<<"Block in the middle"<<endl; cout<<m.block<2,2>(1,1)<<endl<<endl; for(int i = 1;i <= 3;++i) { cout<<"Block of size "<<i<<"x"<<i<<endl; cout<<m.block(0,0,i,i)<<endl<<endl; } }

    执行结果如下:

    Block in the middle 6 7 10 11 Block of size 1x1 1 Block of size 2x2 1 2 5 6 Block of size 3x3 1 2 3 5 6 7 9 10 11

    上面的示例中,.block() 被应用为左值操作,即从中读取数据。事实上,它也可以被用作为右值操作,即也可往里面写入数据。下面是一个右值应用实例。

    #include <iostream> #include "Eigen/Dense" using namespace std; using namespace Eigen; int main() { Array22f m; m<< 1,2, 3,4; Array44f a = Array44f::Constant(0.6); cout<<"Here is the array a:"<<endl<<a<<endl<<endl; a.block<2,2>(1,1) = m; cout<<"Here is now a with m copied into its central 2x2 block:"<<endl<<a<<endl<<endl; a.block(0,0,2,3) = a.block(2,1,2,3); cout<<"Here is now a with bottom-right 2x3 block copied into top-left 2x2 block:"<<endl<<a<<endl<<endl; }

    执行结果如下:

    Here is the array a: 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 0.6 Here is now a with m copied into its central 2x2 block: 0.6 0.6 0.6 0.6 0.6 1 2 0.6 0.6 3 4 0.6 0.6 0.6 0.6 0.6 Here is now a with bottom-right 2x3 block copied into top-left 2x2 block: 3 4 0.6 0.6 0.6 0.6 0.6 0.6 0.6 3 4 0.6 0.6 0.6 0.6 0.6

    .block()方法是一种非常通用的块操作方法。除了这个通用的方法以外,Eigen中还为一些常用的特殊操作提供了特殊的函数。从运行速度的方面来看,你应该在编译阶段尽可能的提供更多的信息。比如,如果你需要操作的块是一个列,那么你可以使用.col()函数。这样Eigen可以得知这个信息以便进行更多的优化。 这些特殊操作方法总结如下。

    3、行子式和列子式

    我们可以使用.col()和.row()方法来操作或者提取一个列或者行。

    块操作方法第i行matrix.row(i);第j列matrix.col(j);

    下面是一个使用示例:

    #include <iostream> #include "Eigen/Dense" using namespace std; using namespace Eigen; int main() { MatrixXf m(3,3); m<< 1,2,3, 4,5,6, 7,8,9; cout<<"Here is the matrix m:"<<endl<<m<<endl; cout<<"2nd Row:"<<m.row(1)<<endl; m.col(2) += 3*m.col(0); cout<<"After adding 3 times the first column into third column,the matrix m is:\n"; cout<<m<<endl; }

    执行结果如下:

    Here is the matrix m: 1 2 3 4 5 6 7 8 9 2nd Row:4 5 6 After adding 3 times the first column into third column,the matrix m is: 1 2 6 4 5 18 7 8 30

    4、边角子矩阵

    Eigen提供了从边角开始提取子矩阵的方法,比如.topLeftCorner()表示从左上角开始提取子矩阵。这些操作总结如下:

    块操作动态矩阵版本固定矩阵版本左上角pxqmatrix.topLeftCorner(p,q);matrix.topLeftCorner<p,q>();左下角pxqmatrix.bottomLeftCorner(p,q);matrix.bbottomLeftCorner<p,q>();右上角pxqmatrix.topRightCorner(p,q);matrix.topRightCorner<p,q>();右下角pxqmatrix.bottomRightCorner(p,q);matrix.bottomRightCorner<p,q>();前p行matrix.topRows(p);matrix.topRows<p>();后p行matrix.bottomRows(p);matrix.bottomRows<p>();前q列matrix.leftCols(q);matrix.leftCols<q>();后q列matrix.rightCols(q);matrix.rightCols<q>();

    下面是一个使用示例:

    #include <iostream> #include "Eigen/Dense" using namespace std; using namespace Eigen; int main() { Matrix4f m; m<< 1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16; cout<<"m.leftCols(2)="<<endl<<m.leftCols(2)<<endl<<endl; cout<<"m.bottomRows<2>()="<<endl<<m.bottomRows<2>()<<endl<<endl; m.topLeftCorner(1,3) = m.bottomRightCorner(3,1).transpose(); cout<<"After assignment,m="<<endl<<m<<endl; }

    执行结果如下:

    m.leftCols(2)= 1 2 5 6 9 10 13 14 m.bottomRows<2>()= 9 10 11 12 13 14 15 16 After assignment,m= 8 12 16 4 5 6 7 8 9 10 11 12 13 14 15 16

    5、向量的子向量操作

    Eigen中同样也为向量提供了一些子式的操作方法,总结如下:

    块操作固定向量版本动态向量版本前n个元素vector.head(n);vector.head();后n个元素vector.tail(n);vector.tail();从i开始取n个元素vector.segment(i,n)vector.segment(i);

    再次说明一下,所有对矩阵的操作同样适用于Array,所有对列向量的操作同样适用于行向量。 下面是一个使用示例:

    #include <iostream> #include "Eigen/Dense" using namespace std; using namespace Eigen; int main() { ArrayXf v(6); v<<1,2,3,4,5,6; cout<<"v.head(3)="<<endl<<v.head(3)<<endl<<endl; cout<<"v.tail<3>()="<<endl<<v.tail<3>()<<endl<<endl; v.segment(1,4) *= 2; cout<<"after 'v.segment(1,4) *= 2',v="<<endl<<v<<endl; }

    执行结果如下:

    v.head(3)= 1 2 3 v.tail<3>()= 4 5 6 after 'v.segment(1,4) *= 2',v= 1 4 6 8 10 6
    最新回复(0)