C++ 如何将块压缩行转换为密集矩阵?

C++ 如何将块压缩行转换为密集矩阵?,c++,matrix,sparse-matrix,C++,Matrix,Sparse Matrix,我感兴趣的是创建一个用于以块压缩稀疏行格式存储稀疏矩阵的类。这种存储方法包括将矩阵细分为大小为sz*sz的方形块,并将此块存储在向量BA中,在这里您可以找到有关 基本上,矩阵使用4个向量存储: BA包含以自上而下的左-右顺序存储的子矩阵(块)的元素(size2x2图片中的第一个块是11,12,0,22) AN包含向量BA的每个起始块的索引(在图片情况下,块大小为2x2,因此它包含1,5…) AJ包含块矩阵中块的列索引(图中较小的一个) AI行指针向量,它存储第i行i-th行AI[i+1]-a[

我感兴趣的是创建一个用于以块压缩稀疏行格式存储稀疏矩阵的类。这种存储方法包括将矩阵细分为大小为
sz*sz
的方形块,并将此块存储在向量
BA
中,在这里您可以找到有关 基本上,矩阵使用4个向量存储:

  • BA
    包含以自上而下的左-右顺序存储的子矩阵(块)的元素(size
    2x2
    图片中的第一个块是
    11,12,0,22
  • AN
    包含向量
    BA
    的每个起始块的索引(在图片情况下,块大小为
    2x2
    ,因此它包含
    1,5…
  • AJ
    包含块矩阵中块的列索引(图中较小的一个)

  • AI
    行指针向量,它存储第i行
    i
    -th行
    AI[i+1]-a[i]=第i行中的块数

我正在编写将矩阵从密集格式转换为BCRS格式的构造函数:

template <typename data_type, std::size_t SZ = 2 >
class BCSRmatrix {

   public:

     constexpr BCSRmatrix(std::initializer_list<std::vector<data_type>> dense );  

    auto constexpr validate_block(const std::vector<std::vector<data_type>>& dense,
                                  std::size_t i, std::size_t j) const noexcept ; 

     auto constexpr insert_block(const std::vector<std::vector<data_type>>& dense,
                                                       std::size_t i, std::size_t j) noexcept ;

  private:

    std::size_t bn  ;
    std::size_t bSZ ;
    std::size_t nnz ;
    std::size_t denseRows ;
    std::size_t denseCols ;

    std::vector<data_type>    ba_ ; 
    std::vector<std::size_t>  an_ ;
    std::vector<std::size_t>  ai_ ;
    std::vector<std::size_t>  aj_ ;


    std::size_t index =0 ;

};

template <typename T, std::size_t SZ>
constexpr BCSRmatrix<T,SZ>::BCSRmatrix(std::initializer_list<std::vector<T>> dense_ )
{
      this->denseRows = dense_.size();   
      auto it         = *(dense_.begin());
      this->denseCols = it.size();

      if( (denseRows*denseCols) % SZ != 0 )
      {
            throw InvalidSizeException("Error block size is not multiple of dense matrix size");
      }

     std::vector<std::vector<T>> dense(dense_);
     bSZ = SZ*SZ ;  
     bn  = denseRows*denseCols/(SZ*SZ) ;
     ai_.resize(denseRows/SZ +1);
    ai_[0] = 1;

    for(std::size_t i = 0; i < dense.size() / SZ ; i++)
    {    
        auto rowCount =0;
        for(std::size_t j = 0; j < dense[i].size() / SZ ; j++)
        {
            if(validate_block(dense,i,j))
            {     
                  aj_.push_back(j+1);
                  insert_block(dense, i, j);
                  rowCount ++ ;
            }      

        }
        ai_[i+1] = ai_[i] + rowCount ;
     }
     printBCSR();
}

template <typename T,std::size_t SZ>
inline auto constexpr BCSRmatrix<T,SZ>::validate_block(const std::vector<std::vector<T>>& dense,
                                                       std::size_t i, std::size_t j) const noexcept
{   
   bool nonzero = false ;
   for(std::size_t m = i * SZ ; m < SZ * (i + 1); ++m)
   {
      for(std::size_t n = j * SZ ; n < SZ * (j + 1); ++n)
      {
            if(dense[m][n] != 0) nonzero = true;
      }
   }

   return nonzero ;
}

template <typename T,std::size_t SZ>
inline auto constexpr BCSRmatrix<T,SZ>::insert_block(const std::vector<std::vector<T>>& dense,
                                                       std::size_t i, std::size_t j) noexcept
{   
   //std::size_t value = index;   
   bool firstElem = true ;
   for(std::size_t m = i * SZ ; m < SZ * (i + 1); ++m)
   {
      for(std::size_t n = j * SZ ; n < SZ * (j + 1); ++n)
      {    
            if(firstElem)
            {
                  an_.push_back(index+1);
                  firstElem = false ;
            }
            ba_.push_back(dense[m][n]);
            index ++ ;
      }
   }


template <typename T, std::size_t SZ>
auto constexpr BCSRmatrix<T,SZ>::printBCSR() const noexcept 
{ 

  std::cout << "ba_ :   " ;
  for(auto &x : ba_ ) 
      std::cout << x << ' ' ;
    std::cout << std::endl; 

  std::cout << "an_ :   " ;
  for(auto &x : an_ ) 
      std::cout <<  x << ' ' ;
    std::cout << std::endl; 

  std::cout << "aj_ :   " ;
  for(auto &x : aj_ ) 
      std::cout <<  x << ' ' ;
    std::cout << std::endl; 

   std::cout << "ai_ :   " ; 
   for(auto &x : ai_ ) 
      std::cout << x << ' ' ;
    std::cout << std::endl; 

}
现在只是整个矩阵丢失了我想我在梅的脑海中遗漏了一些东西。。但这应该很容易,但我没抓住重点。。有什么想法吗

从这个4向量到稠密矩阵的倒推怎么样?例如,如何打印整个矩阵

回到稀疏矩阵:

template <typename T, std::size_t SZ> 
auto constexpr BCSRmatrix<T,SZ>::recomposeMatrix() const noexcept {

    std::vector<std::vector<data_type>> sparseMat(denseRows, std::vector<data_type>(denseCols, 0));
    auto BA_i = 0, AJ_i = 0;
    //for each BCSR row
    for(auto r = 0; r < denseRows/SZ; r++){
        //for each Block in row
        for(auto nBlock = 0; nBlock < ai_.at(r+1)-ai_.at(r); nBlock++){  
            //for each subMatrix (Block)
            for(auto rBlock = 0; rBlock < SZ; rBlock++){
                for(auto cBlock = 0; cBlock < SZ; cBlock++){
                    //insert value
                    sparseMat.at(rBlock + r*SZ).at(cBlock + (aj_.at(AJ_i)-1)*SZ) = ba_.at(BA_i);
                    ++BA_i;
                }
            }
        ++AJ_i;
        }
    }
    return sparseMat;
}
我不确定我写的模板是否正确,无论如何算法应该可以工作;如果有问题,请告诉我


编辑

在一个为节省时间和内存而创建的类中,存储稀疏矩阵比使用向量重建整个矩阵更有意义吗

你是对的,我的错;我以为问题是重新组合矩阵。 我使用findBlockIndex作为引用重写了这些方法

template <typename T, std::size_t SZ> 
auto constexpr BCSRmatrix<T,SZ>::printSparseMatrix() const noexcept {      
    //for each BCSR row
    for(auto i=0 ; i < denseRows / SZ ; i++){
        //for each Block sub row.
        for(auto rBlock = 0; rBlock < SZ; rBlock++){
            //for each BCSR col.
            for(auto j = 1; j <= denseCols / SZ; j++){
                //for each Block sub col.
                for(auto cBlock = 0; cBlock < SZ; cBlock++){
                    std::cout<< findValue(i, j, rBlock, cBlock) <<'\t';
                }
            }
            std::cout << std::endl;
        }
    }
}

template <typename T, std::size_t SZ> 
auto constexpr BCSRmatrix<T,SZ>::findValue(const std::size_t i, const std::size_t j, const std::size_t rBlock, const std::size_t cBlock) const noexcept {

    auto index = findBlockIndex(i,j);
    if(index != 0)
        return ba_.at(an_.at(index-1)-1 + cBlock + /* rBlock*2 */ rBlock*SZ);
}    
模板
auto constexpr BCSRmatrix::printSparseMatrix()const noexcept{
//对于每个BCSR行
对于(自动i=0;i对于(auto j=1;j谢谢@Marco D.G.,你的方法的扩展性如何?我的意思是..它可以工作,但在一个为节省时间和内存而创建的类中,它以某种方式存储稀疏矩阵比使用向量来重建整个矩阵更有意义?我知道这是我要求的!你的代码非常优秀!但是你不知道吗试想一个名为
findIndex(i,j)
的方法,在该方法中,如果与零不同,则返回原始矩阵的值,否则返回0?你不认为这应该更好吗?不如打印出整个矩阵,而不是将其存储在向量中??顺便说一句,再次感谢..你的代码工作起来很有魅力:)你是对的@Drudox,我的错;我以为问题在于重新组合矩阵。我使用findBlockIndex作为参考重写了这些方法。如果有问题,请告诉我。向Marco致意:)谢谢@Marco D.G.你给了我很大的帮助:)你确定吗?我试图打印出bbcsr3矩阵,结果很奇怪。你检查过了吗?
1 0 0 0 
2 3 0 0 
0 0 4 5 
0 0 0 6 
template <typename T, std::size_t SZ> 
auto constexpr BCSRmatrix<T,SZ>::recomposeMatrix() const noexcept {

    std::vector<std::vector<data_type>> sparseMat(denseRows, std::vector<data_type>(denseCols, 0));
    auto BA_i = 0, AJ_i = 0;
    //for each BCSR row
    for(auto r = 0; r < denseRows/SZ; r++){
        //for each Block in row
        for(auto nBlock = 0; nBlock < ai_.at(r+1)-ai_.at(r); nBlock++){  
            //for each subMatrix (Block)
            for(auto rBlock = 0; rBlock < SZ; rBlock++){
                for(auto cBlock = 0; cBlock < SZ; cBlock++){
                    //insert value
                    sparseMat.at(rBlock + r*SZ).at(cBlock + (aj_.at(AJ_i)-1)*SZ) = ba_.at(BA_i);
                    ++BA_i;
                }
            }
        ++AJ_i;
        }
    }
    return sparseMat;
}
std::vector<std::vector<int>> sparseMat = bbcsr2.recomposeMatrix();
for(auto i = 0; i < sparseMat.size(); i++){
    for(auto j = 0; j < sparseMat.at(i).size(); j++)
        std::cout<<sparseMat.at(i).at(j) << '\t';
    std::cout << std::endl;
}
template <typename T, std::size_t SZ> 
auto constexpr BCSRmatrix<T,SZ>::printSparseMatrix() const noexcept {      
    //for each BCSR row
    for(auto i=0 ; i < denseRows / SZ ; i++){
        //for each Block sub row.
        for(auto rBlock = 0; rBlock < SZ; rBlock++){
            //for each BCSR col.
            for(auto j = 1; j <= denseCols / SZ; j++){
                //for each Block sub col.
                for(auto cBlock = 0; cBlock < SZ; cBlock++){
                    std::cout<< findValue(i, j, rBlock, cBlock) <<'\t';
                }
            }
            std::cout << std::endl;
        }
    }
}

template <typename T, std::size_t SZ> 
auto constexpr BCSRmatrix<T,SZ>::findValue(const std::size_t i, const std::size_t j, const std::size_t rBlock, const std::size_t cBlock) const noexcept {

    auto index = findBlockIndex(i,j);
    if(index != 0)
        return ba_.at(an_.at(index-1)-1 + cBlock + /* rBlock*2 */ rBlock*SZ);
}