zoukankan      html  css  js  c++  java
  • Eigen子矩阵操作

    1 子矩阵操作简介

    本文翻译自官方的 Using block operations。这篇文章只是我在学习的时候做的记录,可能有些陈旧了,建议直接看官方的文档。

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

    2 块操作的一般使用方法

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

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

    同样需要注意的是在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:
    ";
    	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()表示从左上角开始提取子矩阵。这些操作总结如下:

    块操作 动态矩阵版本 固定矩阵版本
    左上角pxq matrix.topLeftCorner(p,q); matrix.topLeftCorner<p,q>();
    左下角pxq matrix.bottomLeftCorner(p,q); matrix.bbottomLeftCorner<p,q>();
    右上角pxq matrix.topRightCorner(p,q); matrix.topRightCorner<p,q>();
    右下角pxq matrix.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>();
    后n个元素 vector.tail(n); vector.tail<n>();
    从i开始取n个元素 vector.segment(i,n) vector.segment<n>(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
    
  • 相关阅读:
    Linux下端口被占用,关掉端口占用的方法
    对于STM32F103的USART的通讯调试
    第一次本地代码提交到github
    SPI的学习和ESP8266的SPI通讯测试
    ubuntu下minicom安装和简单设置使用
    ubuntu18.04下stlink的一种安装方法
    使用arm-none-eabi-gdb报错error while loading shared libraries: libncurses.so.5: cannot open shared object file: No such file or directory
    在麦芒5手机播放音乐时APPS连上后出现自动重启了(请查找:REBOOT关键字)
    一连上蓝牙后,按音量加键,死机(有LOG)
    启动后,只连上蓝牙后,播放音乐,这时按音量,播放,暂停都没功能(按键是有作用的)
  • 原文地址:https://www.cnblogs.com/yabin/p/6473654.html
Copyright © 2011-2022 走看看