如何有效地删除'非零元素sprase matrix C ++

时间:2017-07-05 13:15:19

标签: c++ sparse-matrix armadillo

我一直在研究一种从大型稀疏(ish)矩阵中去除非零元素的算法,作为一种减少数值解的计算时间到大型耦合ODE系统的方法。 logistic equation

基本思想是,每T个时间步,您可以评估状态矩阵B中的哪些元素大于某个阈值。对于那些被认为无关紧要(即低于阈值)的人,你在稀疏交互矩阵A中删除(设置为零)相关的行/列,这样AxB的计算将需要更少的触发器。(注意,对角线保持非零,所以状态矩阵的相关元素不会爆炸)

算法如下:

  1. 通过B向量扫描少于阈值和记录位置的元素

  2. 迭代A矩阵的非零元素,对应于1中记录的位置并记录位置

  3. 将对应于2.中记录的位置的A元素设置为零。
  4. 我需要分离步骤2.和3.因为如果将稀疏矩阵(arma :: sp_mat)的非零元素设置为零,则会破坏迭代器,因此无法实现结果单程。

    有人可以就如何改进此算法提出任何建议吗?

    (注意我不是计算机科学家,所以我可能没有明显的改进.MMMM很感谢你的尝试!)

    #include <iostream>
    #include <armadillo>
    
    
    using namespace std;
    using namespace arma;
    int main() {
    
    mat A = {{1, 0.2, 0, 0.2, 0, 0, 0.2, 0, 0.2, 0},
             {0, 1, 0.2, 0, 0.2, 0, 0, 0.2, 0 , 0},
             {0, 0, 1, 0.2, 0, 0, 0.2, 0, 0, 0.2},
             {0.2, 0, 0, 1, 0.2, 0, 0.2, 0.2, 0, 0.2},
             {0, 0.2, 0, 0.2, 1, 0.2, 0, 0, 0, 0.2},
             {0, 0, 0.2, 0, 0.2, 1, 0, 0.2, 0, 0},
             {0.2, 0, 0, 0.2, 0.2, 0, 1, 0, 0, 0.2},
             {0, 0.2, 0, 0.2, 0, 0, 0, 1, 0.2, 0},
             {0, 0, 0.2, 0, 0.2, 0.2, 0, 0, 1, 0},
             {0, 0, 0, 0.2, 0, 0.2, 0, 0, 0.2, 1}};
    sp_mat Asp(A); // Interaction matrix in sparse representation
    
    vec B = {1, 1, 0.1, 1, 0.1, 1, 1, 0.1, 1, 1};
    
    double thresh = 0.2;
    
    vec index(Asp.n_rows); // obj for storing locations of insignificant elements b
    
    int count = 0;
    for (int i=0; i<B.n_rows; i++) {
        if (B(i) < thresh) {
            index(count) = i;
            count ++;
        }
    }
    
    index.resize(count);
    
    sp_mat tmp = Asp; // temp copy of interaction matrix
    
    for (int i=0; i<index.n_rows; i++) {
        // iterate through non-zero elements in col corresponding to each element of index
        sp_mat::iterator bc = tmp.begin_col(index(i));
        sp_mat::iterator ec = tmp.end_col(index(i));
    
        // iterate through non-zero elements in row corresponding to each element of index
        sp_mat::row_iterator br = tmp.begin_row(index(i));
        sp_mat::row_iterator er = tmp.end_row(index(i));
    
        // mat for storing locations of non-zero elements to be removed
        mat loc(2, 2 * tmp.n_cols);
    
        int count2 = 0;
        for (auto j = bc; j != ec; j++) {
            loc(0, count2) = j.row();
            loc(1, count2) = j.col();
            count2++;
        }
    
        for (auto j = br; j != er; j++) {
            loc(0, count2) = j.row();
            loc(1, count2) = j.col();
            count2++;
        }
    
        loc.resize(2, count2);
    
        for (int j = 0; j < loc.n_cols; j++) {
            tmp(loc(0, j), loc(1, j)) = 0.0;
        }
    }
    
    tmp.diag().ones();
    
    cout << "Number of non-zero terms interaction matrix = " << Asp.n_nonzero << endl;
    cout << "Number of non-zero terms reduced matrix = " << tmp.n_nonzero << endl;
    }
    

    输出:

    Number of non-zero terms interaction matrix = 45
    Number of non-zero terms reduced matrix = 24
    

0 个答案:

没有答案