4

私は持っています

vector < vector < int > > data_mat ( 3, vector < int > (4) );
vector          < int >   data_vec ( 3                     ); 

ここでdata_mat、は行列および列ベクトルと考えることができ、 withdata_vecのすべての列の内積を計算し、それを別のに格納する方法を探しています。data_matdata_vecvector < int > data_out (4)

とを使用した例http://liveworkspace.org/code/2bW3X5%241は、行列の列の合計を計算するために使用できます。for_eachtransform

sum=vector<int> (data_mat[0].size());
for_each(data_mat.begin(), data_mat.end(),
         [&](const std::vector<int>& c) {
            std::transform(c.begin(), c.end(), sum.begin(), sum.begin(),
                           [](int d1, double d2) 
                             { return d1 + d2; }
                          );
            }
        );

同様の方法で(またはSTL関数を使用するわずかに異なる方法で)、ベクトルを使用して行列列の列内積を計算することは可能ですか?

問題は、'd2 = d1 + d2'トリックが、列の内積の場合には機能しないことです。これを解決するd3も含める方法がある場合(d3 = d3 + d1 * d2)、に三元関数が存在しないようですtransform

4

1 に答える 1

5

実際、既存の列合計アプローチをほぼ1対1で使用できます。std::transform行列行を合計する前にスケーリングする係数は、列ベクトルからの行値であり、行列行と一緒に繰り返されるため、各行で一定であるため、内部ループとして3値は必要ありません。アウターstd::for_each

したがって、必要なのは、行列の行を反復処理し、各完全な行に列ベクトルの対応する値を掛けて、そのスケーリングされた行を合計ベクトルに追加することです。ただし、残念ながら、このためにstd::for_eachは、行列の行と列ベクトルの行の2つの範囲を同時に繰り返す関数が必要になります。これを実現するには、通常の単項std::for_eachを使用し、追加のイテレータを使用して、列ベクトルに対して手動で反復を実行します。

std::vector<int> sum(data_mat[0].size());
auto vec_iter = data_vec.begin();
std::for_each(data_mat.begin(), data_mat.end(), 
              [&](const std::vector<int>& row) {
                 int vec_value = *vec_iter++;    //manually advance vector row
                 std::transform(row.begin(), row.end(), sum.begin(), sum.begin(),
                                [=](int a, int b) { return a*vec_value + b; });
              });

内部での追加の手動反復std::for_eachは、実際には標準ライブラリアルゴリズムの慣用的な使用ではありませんが、残念ながら、使用できるバイナリはありませんstd::for_each


もう1つのオプションはstd::transform、外部ループ(2つの範囲で反復可能)として使用することですが、返す各外部反復で実際には単一の値を計算しないため、外部ラムダからダミー値を返すだけで済みます。ある種のダミー出力イテレータを使用して破棄します。それも最もクリーンな解決策ではありません:

//output iterator that just discards any output
struct discard_iterator : std::iterator<std::output_iterator_tag,
                                        void, void, void, void>
{
    discard_iterator& operator*() { return *this; }
    discard_iterator& operator++() { return *this; }
    discard_iterator& operator++(int) { return *this; }
    template<typename T> discard_iterator& operator=(T&&) { return *this; }
};

//iterate over rows of matrix and vector, misusing transform as binary for_each
std::vector<int> sum(data_mat[0].size());
std::transform(data_mat.begin(), data_mat.end(), 
               data_vec.begin(), discard_iterator(), 
               [&](const std::vector<int>& row, int vec_value) {
                   return std::transform(row.begin(), row.end(), 
                                         sum.begin(), sum.begin(),
                                         [=](int a, int b) { 
                                             return a*vec_value + b;
                                         });
               });

編集:これはすでにコメントで議論されており、質問の理論的性質を理解しています(そして感謝しています)が、実際には動的配列の動的配列はそのような構造的にうまく表現するためのひどい方法であるという提案を含めます-行列のように定義された2D配列。適切な演算子を使用した適切な行列データ構造(コンテンツを連続して格納する)は、ほとんどの場合、より適切な選択です。ただし、その汎用性により、このようなカスタムデータ構造を操作するための標準ライブラリアルゴリズムを使用できます(おそらく、行列型に独自のイテレータを提供させることによっても)。

于 2013-03-06T13:34:41.960 に答える