密集矩阵的特征指数

Eigen Indices of Dense Matrix meeting Condition

本文关键字:特征 指数      更新时间:2023-10-16

我希望从符合条件的密集矩阵中获取行/列索引。就我而言,结果可能很少。例如,使用矩阵

1 5 2
7 6 3
2 3 8

我想获得指示系数大于4或

的位置
(0,1), (1,0), (1,1), (2,2)

我的最初想法包括使用选择或系数操作来构建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)
        }
    }
}

,但这仅采用编译器的优化,并且没有特征的优化/矢量化。

我缺少一种更有效的方法吗?在我的情况下,条件是简单的比较。

感谢您的任何帮助

这里没有太多的矢量化,但是要避免编写两个循环(最好将其用于行 - 莫乔尔存储(,最好的工具是访客:

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 << "nn";
    for(auto p:indices)
        std::cout << '(' << p.first << ',' << p.second << ") ";
    std::cout << 'n';
    return 0;
}