我很感兴趣地创建一个类,用于存储块压缩稀疏行格式的稀疏矩阵

这种存储方法包括将矩阵细分为大小为sz*sz的方形块,并将该块存储在向量BA中,在这里您可以找到关于链接的大部分信息--基本上,矩阵使用4个向量存储:
BA包含按左上角顺序存储的子矩阵(块)的元素( 2x2大小图中的第一个块是11,12,0,22)。AN包含向量BA的每个起始块的索引(在pictur情况下,块大小是2x2,所以它包含1,5 ... )AJ包含块矩阵中块的列索引(图中较小的块)。AI行指针向量,它在i-th行ai[i+1]-a[i] = number of block in i-th row中存储有多少块。我正在编写用于将矩阵从密集格式转换为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;
}以及测试类的主要功能:
# include "BCSRmatrix.H"
using namespace std;
int main(){
BCSRmatrix<int,2> bbcsr2 = {{11,12,0,0,0,0,0,0} ,{0,22,0,0,0,0,0,0} ,{31,32,33,0,0,0,0,0},
{41,42,43,44,0,0,0,0}, {0,0,0,0,55,56,0,0},{0,0,0,0,0,66,67,0},{0,0,0,0,0,0,77,78},{0,0,0,0,0,0,87,88}};
BCSRmatrix<int,4> bbcsr3 = {{11,12,0,0,0,0,0,0} ,{0,22,0,0,0,0,0,0} ,{31,32,33,0,0,0,0,0},
{41,42,43,44,0,0,0,0}, {0,0,0,0,55,56,0,0},{0,0,0,0,0,66,67,0},{0,0,0,0,0,0,77,78},{0,0,0,0,0,0,87,88}};
return 0;
}现在回到问题..。我得到了图中的4向量..。但是从这个4向量到稠密矩阵又如何呢?例如,如何打印出整个矩阵?
编辑:,我已经找到了用向量AN的相对索引绘制图片中的“块矩阵”的方法:
template <typename T,std::size_t SZ>
inline auto constexpr BCSRmatrix<T,SZ>::printBlockMatrix() const noexcept
{
for(auto i=0 ; i < denseRows / SZ ; i++)
{
for(auto j=1 ; j <= denseCols / SZ ; j++)
{
std::cout << findBlockIndex(i,j) << ' ' ;
}
std::cout << std::endl;
}
}
template <typename T, std::size_t SZ>
auto constexpr BCSRmatrix<T,SZ>::findBlockIndex(const std::size_t r, const std::size_t c) const noexcept
{
for(auto j= ai_.at(r) ; j < ai_.at(r+1) ; j++ )
{
if( aj_.at(j-1) == c )
{
return j ;
}
}
}我主要是这样说的:
bbcsr3.printBlockMatrix();
给我一个正确的结果:
1 0 0 0
2 3 0 0
0 0 4 5
0 0 0 6 现在,整个矩阵都不见了,我想我可能会错过一些东西。但这应该是件容易的事,但我不明白..有什么想法吗?
发布于 2017-11-25 22:39:06
从这个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;
}其中:BA_i和AJ_i是各自向量的迭代器。
nBlock将ai_给出的块数保持在行中。
rBlock和cBlock是称为“块”的子矩阵sz*sz的迭代器。
注意:an_仍未使用,您可以尝试用它替换BA_i。
打印矩阵:
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;
}我不确定我写的模板是否正确,无论如何,算法应该能工作;如果有问题,请告诉我。
编辑
在为节省时间和内存而创建的类中,存储稀疏矩阵比使用向量重建整个矩阵更有意义?
你说得对,我的错;我以为问题是重组矩阵。我使用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);
} 我希望能对你有所帮助,向马可问好。
https://stackoverflow.com/questions/47486623
复制相似问题