簡體   English   中英

本征::將稀疏矩陣轉換為行順序或列順序

[英]Eigen:: Cast sparse matrix as, specifically, row order or col order

我有一個內部函數,

Eigen::SparseMatrix<double> & M;

if (M.IsRowMajor)
     return my_func_template<Eigen::SparseMatrix<double,Eigen::RowMajor>&>(M,M.rows());

但是,這不會編譯,因為編譯器認為M不是Eigen::SparseMatrix<double,Eigen::RowMajor> 在C ++ 11的類型安全環境中,如何將引用轉換為Eigen::SparseMatrix<double,Eigen::RowMajor>


例如:

typedef Eigen::SparseMatrix<double> Smat;
typedef Eigen::SparseMatrix<double,Eigen::RowMajor> RMSmat;
typedef Eigen::SparseMatrix<double,Eigen::ColMajor> CMSmat;    

enum direction { row, col};

template<class Mat>
vector<double> sum_along_inner(Mat &M){
    vector<double> sums(M.innerSize(),0);
    for(auto i = 0; i < M.outerSize(); i++){
        for(typename M::InnerIterator it(M,i); it;++it){
            sums[i] += it.value();
        }
    }
}
vector<double> sum_along_axis(Smat &M, direction dir){

    // If I could solve this problem, 
    // 
    // I could also function off these if components, 
    // and re-use them for other order-dependent functions I write
    // so that my top level functions are only about 2-4 lines long

    if(dir == direction::row){
        if(M.IsRowMajor)
            return sum_along_inner<RMSmat>((my question) M);

        //else
        RMsmat Mrowmajor = M;
        return sum_along_inner<RMSmat>(Mrowmajor);
    }
    else { 
       if(!M.IsRowMajor)
            return sum_along_inner<CMSmat>(M);

       // else
       CMSmat Mcolmajor = M;
       return sum_along_inner<CMSmat>((my_question) Mcolmajor);
    }
}

如果我不僅僅執行sum_along_axis ,那么就行數,可讀性等方面而言,代碼復雜度是僅能解決我要解決的這個問題的兩倍。

否則,我不能抽象該循環,而我必須對列主行和行主行重復它……因為我不能僅僅假設我不會從sum_along_axis從中交換主序的函數調用sum_along_axis 。默認的Eigen::ColMajorEigen::RowMajor ...

此外,如果我以mb大小的稀疏矩陣進行操作,其尺寸太笨拙以致無法以密集矩陣形式表示,那么如果我這樣做,我會注意到速度顯着下降(這違背了使用稀疏矩陣開始的目的)不要編寫與順序無關的 可組合函數,而僅在需要時才轉換主要順序。

因此,除非我解決此問題,否則行數和/或函數數或多或少會開始組合。

正如我在第一條評論中所寫, M.IsRowMajor將永遠是錯誤的。 這是因為Eigen::SparseMatrix始終具有兩個模板參數,其中第二個默認為Eigen::ColMajor

如果您想編寫一個既接受行矩陣又接受列矩陣的函數,則需要編寫類似

template<int mode>
vector<double> sum_along_axis(Eigen::SparseMatrix<double,mode> const &M, direction dir)
    if(dir == direction::row){
        return sum_along_inner<RMSmat>(M); // implicit conversion if necessary
    }
    else { 
        return sum_along_inner<CMSmat>(M); // implicit conversion if necessary
    }
}

您需要重寫sum_along_inner以接受const引用才能使隱式轉換起作用:

template<class Mat>
vector<double> sum_along_inner(Mat const &M){
    vector<double> sums(M.outerSize(),0); // sums needs to have size M.outerSize()
    for(auto i = 0; i < M.outerSize(); i++){
        for(typename M::InnerIterator it(M,i); it;++it){
            sums[i] += it.value();
        }
    }
}

如果要避免從行優先轉換為列優先(反之亦然),則應編寫一個沿外部維求和的函數,並在主函數中確定要調用的函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM