2013-01-02 24 views
8

EigenはC++のよく知られた行列ライブラリです。私は、単純に行列の最後にアイテムをプッシュする組み込み関数を見つけるのが面倒です。Eigen MatrixXdはC++でプッシュバック

Eigen::MatrixXd matrix(10, 3); 
long int count = 0; 
long int topCount = 10; 
for (int i = 0; i < listLength; ++i) { 
    matrix(count, 0) = list.x; 
    matrix(count, 1) = list.y; 
    matrix(count, 2) = list.z; 
    count++; 
    if (count == topCount) { 
     topCount *= 2; 
     matrix.conservativeResize(topCount, 3); 
    } 
} 
matrix.conservativeResize(count, 3); 

そして、これは(構文の一部が出てかもしれ)動作します。現在、私はそれはこのように行うことができることを知っています。しかし、それはかなり単純なことのために巻き込まれました。すでに組み込まれている機能はありますか?

答えて

13

固有行列にはそのような関数はありません。この理由は、そのような関数が非常に遅いか、または過剰なメモリを使用するためです。

push_backは非常に高価ではないため、実行したときにスペースが足りなくなったときに、何らかの要因でマトリックスの容量を増やす必要があります。しかし、行列を扱うときには、メモリ使用量が問題になることが多いので、行列の容量を必要以上に大きくすることは問題になる可能性があります。 代わりに、操作がO(n*m)になるたびに、rows()またはcols()のサイズを増やしてください。行列全体を埋めるためにこれを行うことは、適度なサイズの行列でさえかなり遅くなるO(n*n*m*m)です。

さらに、線形代数行列およびベクトルサイズは、ほとんど常に一定であり、事前にわかっています。行列のサイズを変更すると、行列の以前の値は気にしません。これは、std::vectorresizeとは異なり、Eigenのresize関数が古い値を保持しない理由です。

ファイルから読み込むときに、事前に行列のサイズがわからない場合があります。この場合、std::vectorなどの標準コンテナにデータをロードしてからpush_backを使ってデータをロードし、それを既にサイズの大きい行列にコピーするか、またはメモリをきちんと読み込んでサイズを取得した後にもう一度コピーしますその価値。

+1

Eigenでは、コンパイル時にMaxRows MaxColsを定義できるため、実行時間まで正確なサイズがわからなくても、メモリ要件は制限されたままです(resize/push_back操作にメモリ割り当ては不要です)。 size gnzlbg

+1

"さらに、線形代数行列では、ベクトルのサイズはほぼ常に一定であり、事前にわかっています。ほとんどの反復アルゴリズムでは、収束基準が満たされるまで何回の反復が必要であるかはわかりません。 – Lindon

+0

上記の注意点をモジュロにして、私が本当に必要な場合は、大きな行列を割り当てて、行列の使用部分を表すブロックを公開します。プッシュするには、ストレージマトリックスの値を入力し、使用済みの新しい部分をカバーする新しい拡張ブロックを作成します。ストレージマトリクスのサイズを使い切ったら、各ディメンションを2倍にして再割り当てします。これは、std :: vectorと同じく、償却された定数です。一度これをカスタムクラスとしてラップすることができます。 (私は行列と比べてブロックの特定の制限を知らないので、それらを数回使っただけです)。 – THK

7

そのような機能はありませんが、しかし、あなたはこのように自分で何かを構築することができます。

using Eigen::MatrixXd; 
using Eigen::Vector3d; 

template <typename DynamicEigenMatrix> 
void push_back(DynamicEigenMatrix& m, Vector3d&& values, std::size_t row) 
{ 
    if(row >= m.rows()) { 
     m.conservativeResize(row + 1, Eigen::NoChange); 
    } 
    m.row(row) = values; 
} 


int main() 
{ 
    MatrixXd matrix(10, 3); 
    for (std::size_t i = 0; i < 10; ++i) { 
     push_back(matrix, Vector3d(1,2,3), i); 
    } 
    std::cout << matrix << "\n"; 
    return 0; 
} 

これはかかわらず、あまりにも多くのサイズ変更を実行する必要がある場合、恐ろしく遅いことになるだろう。

関連する問題