Eigen How to Concatenate Matrix Along a Specific Dimension

Eigen how to concatenate matrix along a specific dimension?

You can use the comma initializer syntax for that.

Horizontally:

MatrixXd C(A.rows(), A.cols()+B.cols());
C << A, B;

Vertically:

// eigen uses provided dimensions in declaration to determine
// concatenation direction
MatrixXd D(A.rows()+B.rows(), A.cols()); // <-- D(A.rows() + B.rows(), ...)
D << A, B; // <-- syntax is the same for vertical and horizontal concatenation

For readability, one might format vertical concatenations with whitespace:

D << A,
B; // <-- But this is for readability only.

how to concatenate Vectors in Eigen?

Like so, assuming you have vec1 and vec2 already:

VectorXd vec_joined(vec1.size() + vec2.size());
vec_joined << vec1, vec2;

(Note that the vector types are simply typedefs of matrix types constrained to have only one column.)

Further reading: Advanced initialization

Eigen::Ref for concatenating matrices

No, Ref is not designed for that. We/You would need to define a new expression for that, that could be called Cat. If you only need to concatenate two matrices horizontally, in Eigen 3.3, this can be implemented in less than a dozen of lines of code as a nullary expression, see some exemple there.

Edit: here is a self-contained example showing that one can mix matrices and expressions:

#include <iostream>
#include <Eigen/Core>

using namespace Eigen;

template<typename Arg1, typename Arg2>
struct horizcat_helper {
typedef Matrix<typename Arg1::Scalar,
Arg1::RowsAtCompileTime,
Arg1::ColsAtCompileTime==Dynamic || Arg2::ColsAtCompileTime==Dynamic
? Dynamic : Arg1::ColsAtCompileTime+Arg2::ColsAtCompileTime,
ColMajor,
Arg1::MaxRowsAtCompileTime,
Arg1::MaxColsAtCompileTime==Dynamic || Arg2::MaxColsAtCompileTime==Dynamic
? Dynamic : Arg1::MaxColsAtCompileTime+Arg2::MaxColsAtCompileTime> MatrixType;
};

template<typename Arg1, typename Arg2>
class horizcat_functor
{
const typename Arg1::Nested m_mat1;
const typename Arg2::Nested m_mat2;

public:
horizcat_functor(const Arg1& arg1, const Arg2& arg2)
: m_mat1(arg1), m_mat2(arg2)
{}

const typename Arg1::Scalar operator() (Index row, Index col) const {
if (col < m_mat1.cols())
return m_mat1(row,col);
return m_mat2(row, col - m_mat1.cols());
}
};

template <typename Arg1, typename Arg2>
CwiseNullaryOp<horizcat_functor<Arg1,Arg2>, typename horizcat_helper<Arg1,Arg2>::MatrixType>
horizcat(const Eigen::MatrixBase<Arg1>& arg1, const Eigen::MatrixBase<Arg2>& arg2)
{
typedef typename horizcat_helper<Arg1,Arg2>::MatrixType MatrixType;
return MatrixType::NullaryExpr(arg1.rows(), arg1.cols()+arg2.cols(),
horizcat_functor<Arg1,Arg2>(arg1.derived(),arg2.derived()));
}

int main()
{
MatrixXd mat(3, 3);
mat << 0, 1, 2, 3, 4, 5, 6, 7, 8;

auto example1 = horizcat(mat,2*mat);
std::cout << example1 << std::endl;

auto example2 = horizcat(VectorXd::Ones(3),mat);
std::cout << example2 << std::endl;
return 0;
}

C++ Eigen: How to concatenate matrices dynamically (pointer issue?)

What do you mean you don't know the size? You can use the member functions cols()/rows() to get the size. Also, I assume by concatenation you mean direct sum? In that case, you can do something like

#include <iostream>
#include <Eigen/Dense>

int main()
{
Eigen::MatrixXd *A = new Eigen::MatrixXd(2, 2);
Eigen::MatrixXd *B = new Eigen::MatrixXd(3, 3);
*A << 1, 2, 3, 4;
*B << 5, 6, 7, 8, 9, 10, 11, 12, 13;

Eigen::MatrixXd *result = new Eigen::MatrixXd(A->rows() + B->rows(), A->cols() + B->cols());
result->Zero(A->rows() + B->rows(), A->cols() + B->cols());
result->block(0, 0, A->rows(), A->cols()) = *A;
result->block(A->rows(), A->cols(), B->rows(), B->cols()) = *B;

std::cout << *result << std::endl;

delete A;
delete B;
delete result;
}

So first make sure it works for 2 matrices, test it, then extend it to N.

Eigen vertical stacking rows into Matrix

TLDR: Write something like this:

CoefficientMatrix A(2*N, 9);

for (int i = 0; i < N; i++) {
CoefficientRow ax;
CoefficientRow ay;
// fill in ax and ay
A.row(2*i) = ax;
A.row(2*i+1) = ay;
}

The reason of your error is (as Avi explained) that the operator<< is intended to fill an entire matrix at once. In fact, calling operator<<(Array &A, Array const &b) assigns b to the top-left corner of A and returns a proxy-object which holds a reference to A and keeps track of how much entries of A already got assigned to (stored in m_row, m_currentBlockRows, m_col) and overloads operator, which assigns the next expression to the corresponding position of a and increases the position accordingly. Finally, when that proxy object gets destructed (which usually happens "at the ;") the destructor checks if all entries of A have been filled (and raises a failed assertion, if not).

If you prefer to use the << , syntax you could also write:

    A.middleRows<2>(2*i) << ax, ay;

With optimizations enabled that should generate the same code as the simple implementation above (so choose whichever is easier to read for you).


N.B.: You could technically (ab)use the CommaInitializer in a loop, by constructing it outside the loop, assigning it to a variable and then only use the , operator inside the loop. I'll intentionally won't give more details on how to do that ...

Eigen: Concatenating matrices and vectors

Does this count as elegant enough?

#include <Eigen/Sparse>
#include <iostream>

using namespace Eigen;
using std::cout;
using std::endl;

int main(int argc, char *argv[])
{

Matrix4f m = Matrix4f::Random();
Matrix3f A = Matrix3f::Constant(0.1);
Vector4f b = Vector4f::Constant(0.2), c = Vector4f::Constant(0.3);
cout << m << endl << endl;
cout << A << endl << endl;
cout << b << endl << endl;
cout << c << endl << endl;

m.block(0, 0, 3, 3) = A;
m.col(3) = b;
m.row(3) = c;

cout << m << endl << endl;

return 0;
}

Note that your question is kinda ambiguous, as the (3,3) position will be determined by the order of assignment between b and c.

Append column to matrix, using Eigen library

You can use conservativeResize for that purpose:

mat.conservativeResize(mat.rows(), mat.cols()+1);
mat.col(mat.cols()-1) = vec;

How replicate eigen::matrix dynamically

The correct way to achieve the same effect as the python's numpy version in C++ would be:

B.replicate<1, 100>(); 

The above will do the replication as you want.

Or you can use:

B.replicate(1, A.rows());


Related Topics



Leave a reply



Submit