2017-06-12 106 views
0

我想寫一個函數具有以下簽名矢量化一個對稱矩陣

VectorXd vectorize (const MatrixXd&); 

它返回一個對稱矩陣的內容在VectorXd形式,沒有重複的元素。例如,

int n = 3; // n may be much larger in practice. 
MatrixXd sym(n, n); 
sym << 9, 2, 3, 
     2, 8, 4, 
     3, 4, 7; 

std::cout << vectorize(sym) << std::endl; 

應該返回:

9 
2 
3 
8 
4 
7 

vec元素的順序並不重要,只要它是系統性的。對我而言,重要的是返回sym的數據而沒有重複的元素,因爲sym總是假定爲對稱的。也就是說,我想以VectorXd的形式返回sym的上部或下部三角形「視圖」元素。

我天真地執行了vectorize嵌套的for循環,但是這個函數可能會在我的程序中經常被調用(超過100萬次)。因此,我的問題是:什麼是編寫vectorize的計算最有效的方法?我曾希望能使用Eigen的triangularView,但我看不出如何。

預先感謝您。

+1

看起來你需要使用'TriangularView'和'Map'。 – TriskalJM

+1

此功能請求相關聯:http://eigen.tuxfamily.org/bz/show_bug.cgi?id=42(請參閱特別是備註2的包裝方式 - 您還必須或多或少地執行此操作手動,雖然)。 – chtz

回答

1

關於效率,你可以寫一個單一的與逐列(因此矢量)拷貝循環:

VectorXd res(mat.rows()*(mat.cols()+1)/2); 
Index size = mat.rows(); 
Index offset = 0; 
for(Index j=0; j<mat.cols(); ++j) { 
    res.segment(offset,size) = mat.col(j).tail(size); 
    offset += size; 
    size--; 
} 

在實踐中,我想到的是,編譯器已經完全向量化的嵌套循環,因而速度應該大致相同。

+0

謝謝你的回答。我編輯了一個小錯誤:'size - '應該在'offset + = size'之後。 – tmnol

+0

你能解釋一下爲什麼你使用'Index'而不是'int'嗎?我還沒有見過之前使用的'Index'類。 – tmnol

+2

@tmnol'Eigen :: Index'(默認情況下)只是std :: ptrdiff_t'的一個typedef,它是64位平臺上的一個64位整數。 – chtz