2012-11-08 53 views
8

Iamは私のプロジェクトにEigenライブラリを使用しています。私はEigenの与えられた行列から特定の行または列を削除する方法を探しています。 Iamはうまくいかない。Eigenライブラリを使用している特定の行または列を削除する方法C++

MatrixXd A = X1 X2 X3 X4 
      Y1 Y2 Y3 Y4 
      Z1 Z2 Z3 Z4 
      A1 A2 A3 A4 
MatrixXd Atransform = X1 X2 X4 
         Y1 Y2 Y4 
         Z1 Z2 Z4 
         A1 A2 A4 
enter code here 

のように、行列全体を反復処理したり、行列Aをブロック演算したりすること以外は、それを簡単に行う方法はありますか?

+1

ブロック操作以外の方法はないと思います。 – Jakob

答えて

9

は少しクリーナーです:

void removeRow(Eigen::MatrixXd& matrix, unsigned int rowToRemove) 
{ 
    unsigned int numRows = matrix.rows()-1; 
    unsigned int numCols = matrix.cols(); 

    if(rowToRemove < numRows) 
     matrix.block(rowToRemove,0,numRows-rowToRemove,numCols) = matrix.block(rowToRemove+1,0,numRows-rowToRemove,numCols); 

    matrix.conservativeResize(numRows,numCols); 
} 

void removeColumn(Eigen::MatrixXd& matrix, unsigned int colToRemove) 
{ 
    unsigned int numRows = matrix.rows(); 
    unsigned int numCols = matrix.cols()-1; 

    if(colToRemove < numCols) 
     matrix.block(0,colToRemove,numRows,numCols-colToRemove) = matrix.block(0,colToRemove+1,numRows,numCols-colToRemove); 

    matrix.conservativeResize(numRows,numCols); 
} 
+0

これは一般的にうまくいくはずですが、 Eigenがブロックを左から右(または上から下)にコピーすることは保証されていないため、理論的にエイリアシングの問題が発生する可能性があります。 – chtz

+0

@chtz:この問題を避けるには、 '.eval()'関数を使います。 – davidhigh

1

私はC++で非常に新しいですが、このコードはアプリケーションで動作します。

フルダイナミックマトリックスでのみ動作しますが、それを適応させることができます。

誰かがより良い方法を持っている場合は、私が本当に学びたいと思っていることを教えてください。ブロック機能を使用して

template<typename ScalarType> 
void MatrixXdRemoveCol(Eigen::Matrix<ScalarType,-1,-1,0,-1,-1> *mat, int colindex) 
{ 
    Eigen::Matrix<ScalarType,-1,-1,0,-1,-1> *auxmat = new Eigen::Matrix<ScalarType,-1,-1,0,-1,-1>; 

    *auxmat = *mat; 

    mat->resize(mat->rows(),mat->cols()-1); 

    int rightColsSize = auxmat->cols()-colindex-1; 

    mat->leftCols(colindex) = auxmat->leftCols(colindex); 
    mat->rightCols(rightColsSize) = auxmat->rightCols(rightColsSize); 
} 

template<typename ScalarType> 
void MatrixXdRemoveCols(Eigen::Matrix<ScalarType,-1,-1,0,-1,-1> *mat, std::vector<int>* cols) 
{ 
    for(auto iter = cols->rbegin();iter != cols->rend();iter++) 
     MatrixXdRemoveCol<ScalarType>(mat,*iter); 
} 

template<typename ScalarType> 
void MatrixXdRemoveRow(Eigen::Matrix<ScalarType,-1,-1,0,-1,-1> *mat, int rowindex) 
{ 
    Eigen::Matrix<ScalarType,-1,-1,0,-1,-1> *auxmat = new Eigen::Matrix<ScalarType,-1,-1,0,-1,-1>; 

    *auxmat = *mat; 

    mat->resize(mat->rows()-1,mat->cols()); 

    int BottomRowsSize = auxmat->rows()-rowindex-1; 

    mat->topRows(rowindex) = auxmat->topRows(rowindex); 
    mat->bottomRows(BottomRowsSize) = auxmat->bottomRows(BottomRowsSize); 
} 
+2

私は固有ライブラリに慣れていませんが、一般的なC++の見方では、関数にメモリリークがあるようです:auxmatsを割り当てますが、それらは削除しないでください。 – cybevnm

+0

一般的に、C++を書くときには 'new'を避けるべきです - あなたが本当に必要としていることが分かっていなければ、何をしているのか知っていなければなりません。代わりに 'Eigen :: Matrix auxmat = mat'と書くだけです(そして、ポインタではなく参照によって' mat'を渡します)。 – chtz

0

bottomRows/rightColsを使用し、アンドリューの答えを向上させるために。

void removeRow(Eigen::MatrixXd& matrix, unsigned int rowToRemove) 
{ 
    unsigned int numRows = matrix.rows()-1; 
    unsigned int numCols = matrix.cols(); 

    if(rowToRemove < numRows) 
     matrix.block(rowToRemove,0,numRows-rowToRemove,numCols) = matrix.bottomRows(numRows-rowToRemove); 

    matrix.conservativeResize(numRows,numCols); 
} 

void removeColumn(Eigen::MatrixXd& matrix, unsigned int colToRemove) 
{ 
    unsigned int numRows = matrix.rows(); 
    unsigned int numCols = matrix.cols()-1; 

    if(colToRemove < numCols) 
     matrix.block(0,colToRemove,numRows,numCols-colToRemove) = matrix.rightCols(numCols-colToRemove); 

    matrix.conservativeResize(numRows,numCols); 
} 
0

次の静的バージョンは、特定の用途(およびEigenのコンパイル時の効率の精神に沿ってより多くの場合)により優れています。この場合、行なしで新しい行列を作成します。同様の機能を列を使用して作成することができます.leftCols() .rightCols()

template<typename T> 
inline constexpr auto removeRow(const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& matrix, const int& rowNum) 
{ 
    return (Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>(matrix.rows() - 1, matrix.cols()) 
     << static_cast<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>>(matrix.topRows(rowNum - 1)), 
     static_cast<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>>(matrix.bottomRows(matrix.rows() - rowNum))).finished(); 
} 

お楽しみください!

関連する問題