稠密矩阵满足条件的特征指数
Eigen Indices of Dense Matrix meeting Condition
我希望从满足条件的密集矩阵中获取 row/column 索引。就我而言,结果可能非常稀疏。例如,矩阵
1 5 2
7 6 3
2 3 8
我想获取系数大于 4 的指标,或者
(0,1), (1,0), (1,1), (2,2)
我最初的想法包括使用 select or coefficientwise 操作来构建 bool/int 矩阵
0 1 0
1 1 0
0 0 1
然后将其转化为稀疏矩阵
(0,1,1), (1,0,1), (1,1,1), (2,2,1)
然后删除系数值
(0,1), (1,0), (1,1), (2,2)
但是,这需要两次遍历原始矩阵大小的矩阵,原始矩阵可能非常大。
或者类似于伪代码的原始矩阵的简单双循环
for (int i; i < mat.cols(); i++) {
for (int j; j < mat.rows(); j++) {
if(cond(mat(j, i))) {
add_index(i, j, index_list)
}
}
}
但这只需要 Eigen 的 optimizations/vectorizations 的编译器优化和 none。
有没有我想念的更有效的方法?在我的例子中,条件是简单的比较。
感谢您的帮助
这里没有太多要矢量化的内容,但是为了避免编写两个循环(对于行优先存储最好将其反转),最好的工具是访问者:
mat.visit(some_visitor);
遗憾的是,访问者不能是简单的 lambda,因为 visit
为第一个元素调用方法 init(val,0,0)
。这对于类似还原的访问者很有用,但并非总是如此。为了使 visit
接受一个简单的 lambda,您可以使用以下助手:
template<typename Func>
struct lambda_as_visitor_wrapper : Func {
lambda_as_visitor_wrapper(const Func& f) : Func(f) {}
template<typename S,typename I>
void init(const S& v, I i, I j) { return Func::operator()(v,i,j); }
};
template<typename Mat, typename Func>
void visit_lambda(const Mat& m, const Func& f)
{
lambda_as_visitor_wrapper<Func> visitor(f);
m.visit(visitor);
}
对于你的情况,你可以这样写:
int main() {
int n = 5;
double th = 0.5;
Eigen::MatrixXd M = Eigen::MatrixXd::Random(n,n);
std::vector<std::pair<int,int>> indices;
visit_lambda(M,
[&indices,th](double v, int i, int j) {
if(v>th)
indices.push_back(std::make_pair(i,j));
});
std::cout << M << "\n\n";
for(auto p:indices)
std::cout << '(' << p.first << ',' << p.second << ") ";
std::cout << '\n';
return 0;
}
我希望从满足条件的密集矩阵中获取 row/column 索引。就我而言,结果可能非常稀疏。例如,矩阵
1 5 2
7 6 3
2 3 8
我想获取系数大于 4 的指标,或者
(0,1), (1,0), (1,1), (2,2)
我最初的想法包括使用 select or coefficientwise 操作来构建 bool/int 矩阵
0 1 0
1 1 0
0 0 1
然后将其转化为稀疏矩阵
(0,1,1), (1,0,1), (1,1,1), (2,2,1)
然后删除系数值
(0,1), (1,0), (1,1), (2,2)
但是,这需要两次遍历原始矩阵大小的矩阵,原始矩阵可能非常大。
或者类似于伪代码的原始矩阵的简单双循环
for (int i; i < mat.cols(); i++) {
for (int j; j < mat.rows(); j++) {
if(cond(mat(j, i))) {
add_index(i, j, index_list)
}
}
}
但这只需要 Eigen 的 optimizations/vectorizations 的编译器优化和 none。
有没有我想念的更有效的方法?在我的例子中,条件是简单的比较。
感谢您的帮助
这里没有太多要矢量化的内容,但是为了避免编写两个循环(对于行优先存储最好将其反转),最好的工具是访问者:
mat.visit(some_visitor);
遗憾的是,访问者不能是简单的 lambda,因为 visit
为第一个元素调用方法 init(val,0,0)
。这对于类似还原的访问者很有用,但并非总是如此。为了使 visit
接受一个简单的 lambda,您可以使用以下助手:
template<typename Func>
struct lambda_as_visitor_wrapper : Func {
lambda_as_visitor_wrapper(const Func& f) : Func(f) {}
template<typename S,typename I>
void init(const S& v, I i, I j) { return Func::operator()(v,i,j); }
};
template<typename Mat, typename Func>
void visit_lambda(const Mat& m, const Func& f)
{
lambda_as_visitor_wrapper<Func> visitor(f);
m.visit(visitor);
}
对于你的情况,你可以这样写:
int main() {
int n = 5;
double th = 0.5;
Eigen::MatrixXd M = Eigen::MatrixXd::Random(n,n);
std::vector<std::pair<int,int>> indices;
visit_lambda(M,
[&indices,th](double v, int i, int j) {
if(v>th)
indices.push_back(std::make_pair(i,j));
});
std::cout << M << "\n\n";
for(auto p:indices)
std::cout << '(' << p.first << ',' << p.second << ") ";
std::cout << '\n';
return 0;
}