1. 程式人生 > >eigen稀疏矩陣拼接(基於塊操作的二維拼接)的思考

eigen稀疏矩陣拼接(基於塊操作的二維拼接)的思考

eigen稀疏矩陣拼接(塊操作)

關於稀疏矩陣的塊操作:參考官方連結

However, for performance reasons, writing to a sub-sparse-matrix is much more limited, and currently only contiguous sets of columns (resp. rows) of a column-major (resp. row-major) SparseMatrix are writable. Moreover, this information has to be known at compile-time, leaving out methods such as block(…) and corner*(…). The available API for write-access to a SparseMatrix are summarized below:

上面規則對應的示例:

SparseMatrix<double,ColMajor> sm1;
sm1.col(j) = ...;
sm1.leftCols(ncols) = ...;
sm1.middleCols(j,ncols) = ...;
sm1.rightCols(ncols) = ...;

SparseMatrix<double,RowMajor> sm2;
sm2.row(i) = ...;
sm2.topRows(nrows) = ...;
sm2.middleRows(i,nrows) = ...;
sm2.bottomRows(nrows) = ...
;

總結為一句話:列優先的稀疏矩陣只能進行列向操作,行優先的稀疏矩陣只能進行橫向操作

  • 這個限制說明很多Dense矩陣的塊操作對Sparse矩陣來說就不成立了:

    • 對正常的Dense矩陣來說,拼接比較方便,可以直接使用:

      M << m1, m2;
      
      M << m1,
           m2;
    • Dense矩陣可以對整個稀疏矩陣的某個block進行修改,比如只是對上述D部分進行修改,稀疏矩陣是不行的

    • Sparse矩陣使用的塊操作更多的用讀取許可權,而沒有寫許可權
  • 在這個限制的前提下,當我們想進行兩維稀疏矩陣的拼接的時候就會很矛盾,舉個例子,我們現在有四個稀疏矩陣A B C D,如下:

    M=[ABCD]

    參考上面的規則程式碼,如果所有的稀疏矩陣都使用列優先,那麼可以將A B進行列向拼接,即[AB],C D也一樣[CD],但是之後我們就無法將結果的[AB][CD]的結果進行橫向拼接為[ABCD]了。

  • 解決方案

    • 笨方法,用insert進行逐個插值

      此時藉助迭代器是一個不錯的選擇,給出一段示例程式:

      Eigen::SparseMatrix<double> M_sparse(2*npixels, 2*npixels);
      M_sparse.reserve(FU_sparse.nonZeros() + FV_sparse.nonZeros());
      for(int c=0; c<FU_sparse.cols(); ++c)
      {
          for(Eigen::SparseMatrix<double>::InnerIterator itU(FU_sparse, c); itU; ++itU)
          {
              if (itU.value())
              {
                  M_sparse.insert(itU.row(), c) = -itU.value();
              }
          }
      }

      問題是,當非零元素的數目過w的時候,上述hash-map的insert弊端就會凸顯出來,也是很耗時的。

    • 在上述限制的前提下利用現有介面實現上述過程

      A=[1234]

      B=[abcd]

      C=[11121314]

      D=[ABCD]

      我們想要的結果是:
      M=[12ab34cd1112AB1314CD]

      1. 對A、B、C、D進行轉置得到
        A=[1324]

        B=[acbd]

        C=[11131214]

        D=[ACBD]

      2. 將A和C、B和D進行列向拼接,得到: