删除 Eigen::SparseMatrix 的空行
remove empty rows of an Eigen::SparseMatrix
我从三元组列表
构建了一个稀疏矩阵mat
Eigen::SparseMatrix<double, Eigen::RowMajor> mat(Nbins,Ndata);
mat.setFromTriplets(tripletList.begin(), tripletList.end());
现在我想创建一个新矩阵ret
,它只包含前一个矩阵的非空行。我是这样做的
Eigen::SparseMatrix<double, Eigen::RowMajor> ret(Nbins,Ndata);
unsigned Nrow=0;
for (unsigned i=0; i<Nbins; ++i) {
auto mrow = mat.row(i);
if (mrow.sum()>0) {
ret.row(Nrow++) = mrow;
}
}
ret.conservativeResize(Nrow,Ndata);
但是,这样做速度慢且效率低下。慢是因为快速分析表明它大部分时间都花在 ret.row(Nrow++) = mrow;
上。效率低下,因为我们还复制了所有数据两次。
有更好的解决办法吗?我觉得必须 fiddle 使用内部向量,但我对它们感到困惑,而且我不知道使用它们是如何保证用户安全的。
编辑:在我的应用程序中,矩阵主要是行,我想删除空行。不需要 mat
,只需 ret
。所有系数都是正的,因此我检查非零行的方式。三元组已排序但列优先。没有重复的三胞胎。
找到了!我没有编写手工制作的 setFromTriplets,而是修改了 tripletList。 Eigen::Triplet的界面让它变得非常简单。
//get which rows are empty
std::vector<bool> has_value(Nbins,false);
for (auto tr : tripletList) has_value[tr.row()] = true;
//create map from old to new indices
std::map<unsigned,unsigned> row_map;
unsigned new_idx=0;
for (unsigned old_idx=0; old_idx<Nbins; old_idx++)
if(has_value[old_idx])
row_map[old_idx]=new_idx++;
//make new triplet list, dropping empty rows
std::vector<Eigen::Triplet<double> > newTripletList;
newTripletList.reserve(Ndata);
for (auto tr : tripletList)
newTripletList.push_back(
Eigen::Triplet<double>(row_map[tr.row()],tr.col(),tr.value()));
//form new matrix and return
Eigen::SparseMatrix<double, Eigen::RowMajor> ret(new_idx,Ndata);
ret.setFromTriplets(newTripletList.begin(), newTripletList.end());
我从三元组列表
构建了一个稀疏矩阵mat
Eigen::SparseMatrix<double, Eigen::RowMajor> mat(Nbins,Ndata);
mat.setFromTriplets(tripletList.begin(), tripletList.end());
现在我想创建一个新矩阵ret
,它只包含前一个矩阵的非空行。我是这样做的
Eigen::SparseMatrix<double, Eigen::RowMajor> ret(Nbins,Ndata);
unsigned Nrow=0;
for (unsigned i=0; i<Nbins; ++i) {
auto mrow = mat.row(i);
if (mrow.sum()>0) {
ret.row(Nrow++) = mrow;
}
}
ret.conservativeResize(Nrow,Ndata);
但是,这样做速度慢且效率低下。慢是因为快速分析表明它大部分时间都花在 ret.row(Nrow++) = mrow;
上。效率低下,因为我们还复制了所有数据两次。
有更好的解决办法吗?我觉得必须 fiddle 使用内部向量,但我对它们感到困惑,而且我不知道使用它们是如何保证用户安全的。
编辑:在我的应用程序中,矩阵主要是行,我想删除空行。不需要 mat
,只需 ret
。所有系数都是正的,因此我检查非零行的方式。三元组已排序但列优先。没有重复的三胞胎。
找到了!我没有编写手工制作的 setFromTriplets,而是修改了 tripletList。 Eigen::Triplet的界面让它变得非常简单。
//get which rows are empty
std::vector<bool> has_value(Nbins,false);
for (auto tr : tripletList) has_value[tr.row()] = true;
//create map from old to new indices
std::map<unsigned,unsigned> row_map;
unsigned new_idx=0;
for (unsigned old_idx=0; old_idx<Nbins; old_idx++)
if(has_value[old_idx])
row_map[old_idx]=new_idx++;
//make new triplet list, dropping empty rows
std::vector<Eigen::Triplet<double> > newTripletList;
newTripletList.reserve(Ndata);
for (auto tr : tripletList)
newTripletList.push_back(
Eigen::Triplet<double>(row_map[tr.row()],tr.col(),tr.value()));
//form new matrix and return
Eigen::SparseMatrix<double, Eigen::RowMajor> ret(new_idx,Ndata);
ret.setFromTriplets(newTripletList.begin(), newTripletList.end());