Eigen入門之密集矩陣 4 - 塊操作

簡介

Eigen 中Matrix/Array提供了.block()來進行block區塊操作,這是面向係數提供的操作功能。

語法

Eigen中提供了2種語法,針對產生的結果是一致的。但存在性能上的不同,任何時候,使用fixed-size模式都會得到更好地性能優化。

分類 語法 說明
dynamic-size matrix.block(i,j,p,q); 執行時才知道維度大小(p,q)。
fixed-size matrix.block<p,q>(i,j); 編譯時指定維度大小(p,q)。

解釋: 區塊的維度大小尺寸:(p,q), 起始的位置:(i,j)。同樣的,位置索引從0開始。

查看一個簡單的示例:

//matrix_block1.cpp

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

using namespace Eigen;
using namespace std;

int main()
{
  Eigen::MatrixXf m(4,4);
  m <<  1, 2, 3, 4,
        5, 6, 7, 8,
        9,10,11,12,
       13,14,15,16;
  
  cout << "matrix m:" << endl << m <<endl<<endl;

  cout<<"-----------------"<<endl;

  cout << "Block in the middle -- m.block<2,2>(1,1)" << endl;
  cout << m.block<2,2>(1,1) << endl << endl;

  cout<<"-----------------"<<endl;
  
  for (int i = 1; i <= 3; ++i)
  {
    cout << "Get from (0,0), Block of size " << i << "x" << i << endl;
    cout << m.block(0,0,i,i) << endl << endl;
  }

  cout<<"-----------------"<<endl;

  for (int i = 1; i <= 3; ++i)
  {
    cout << "Get from (1,1), Block of size " << i << "x" << i << endl;
    cout << m.block(1,1,i,i) << endl << endl;
  }
}

執行的結果:

$ g++   -I /usr/local/include/eigen3 matrix_block1.cpp -o matrix_block1
$ 
$ ./matrix_block1 
matrix m:
 1  2  3  4
 5  6  7  8
 9 10 11 12
13 14 15 16

-----------------
Block in the middle -- m.block<2,2>(1,1)
 6  7
10 11

-----------------
Get from (0,0), Block of size 1x1
1

Get from (0,0), Block of size 2x2
1 2
5 6

Get from (0,0), Block of size 3x3
 1  2  3
 5  6  7
 9 10 11

-----------------
Get from (1,1), Block of size 1x1
6

Get from (1,1), Block of size 2x2
 6  7
10 11

Get from (1,1), Block of size 3x3
 6  7  8
10 11 12
14 15 16

block()不僅可以用於右值,也可以用於左值。下面來個Array的簡單示例。

//matrix_block2.cpp

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

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;
}

此示例中,在一個4X4的常量二維數組中,修改(2,2,1,1)區塊的係數,此次修改操作對應大小指定爲1X1了,取值來源區塊爲2X2數組。

執行結果如下,最後劃線的部分是最後一次block區塊替換的部分:

$ g++   -I /usr/local/include/eigen3 matrix_block2.cpp -o matrix_block2
$
$ ./matrix_block2
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中提供了更好地API方法col(), row()

  • matrix.row(i) : 第 i 行;
  • matrix.col(j) : 第 j 列;

示例:

//matrix_block3.cpp
#include <Eigen/Dense>
#include <iostream>

using namespace std;

int main()
{
  Eigen::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 m.col(2) += 3 * m.col(0), the matrix m is:\n";
  cout << m << endl;
}

執行:

$ g++   -I /usr/local/include/eigen3 matrix_block3.cpp -o matrix_block3
promote:eigen david$ ./matrix_block3
Here is the matrix m:
1 2 3
4 5 6
7 8 9
2nd Row: 4 5 6
After m.col(2) += 3 * m.col(0), the matrix m is:
 1  2  6
 4  5 18
 7  8 30

邊角操作

有時候,需要對矩陣的邊角進行操作。Matrix提供了對應的方法函數,可以很變量地進行操作。

target 動態 固定尺寸
左上 matrix.topLeftCorner(p,q); matrix.topLeftCorner<p,q> ();
左下 matrix.bottomLeftCorner(p,q); matrix.bottomLeftCorner<p,q> ();
右上 matrix.topRightCorner(p,q); matrix.topRightCorner<p,q> ();
右上 matrix.bottomRightCorner(p,q); matrix.bottomRightCorner<p,q> ();
頂部q行 matrix.topRows(q); matrix.topRows ();
底部q行 matrix.bottomRows(q); matrix.bottomRows ();
左邊p列 matrix.leftCols§; matrix.leftCols

();

右邊p列 matrix.rightCols(q); matrix.rightCols ();

向量的block塊操作

準對向量、一維數組,Eigen還提供了一組特別的塊操作。

操作 Dynamic 模式 fixed_size 模式
頭部n個 vector.head(n); vector.head();
尾部n個 vector.tail(n); vector.tail();
自i起始的n個 vector.segment(i,n); vector.segment(i);

示例

//matrix_block4.cpp

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

using namespace std;

int main()
{
  Eigen::ArrayXf v(6);
  v << 1, 2, 3, 4, 5, 6;

  Eigen::ArrayXf vv = v.head(3) ;
  cout << "v.head(3) =" << endl << vv << endl << endl;

  Eigen::ArrayXf vvv = v.tail<3>() ;
  cout << "v.tail<3>() = " << endl << vvv << endl << endl;

  v.segment(1,4) *= 2;
  cout << "after 'v.segment(1,4) *= 2', v =" << endl << v << endl;
}

執行:

$ g++   -I /usr/local/include/eigen3 matrix_block4.cpp -o matrix_block4
promote:eigen david$ ./matrix_block4
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

發佈了110 篇原創文章 · 獲贊 108 · 訪問量 67萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章