10

Eigen はよく知られている 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);

そして、これは機能します(構文の一部がアウトになっている可能性があります)。しかし、単純なことを行うにはかなり複雑です。組み込み関数は既にありますか?

4

2 に答える 2

17

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

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

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

マトリックスのサイズが事前にわからない唯一のケースは、ファイルから読み取る場合です。この場合、最初にstd::vector使用などの標準コンテナーにデータをロードしpush_backてから、既にサイズ設定されているマトリックスにコピーするか、メモリが不足している場合は、ファイルを 1 回実行してサイズを取得し、2 回目に値をコピーします。 .

于 2013-01-03T00:59:28.583 に答える
11

そのような関数はありませんが、次のようなものを自分で作成できます。

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;
}

ただし、これがあまりにも多くのサイズ変更を実行する必要がある場合は、非常に遅くなります。

于 2013-01-03T01:10:31.060 に答える