Eigen3: определение матрицы переменного размера - PullRequest
0 голосов
/ 20 мая 2018

Я хочу написать процедуру для создания транспонирования матрицы в виде большой двойной матрицы строк, используя Eigen3 (внутри RcppEigen ).В основном я буду использовать его для матриц разного размера.

В Eigen3 шаблон Matrix принимает 6 аргументов:

  • Три обязательны: (Scalar, RowsAtCompileTime и ColsAtCompileTime)

  • Три необязательных: (Опции, MaxRowsAtCompileTime и MaxColsAtCompileTime) Параметры могут быть RowMajor или ColMajor

Я предпочитаю динамически назначать размеры для матриц, потому что я работаю с большиминаборы данных, и я хочу избежать траты оперативной памяти.

Итак, я написал следующее

Eigen::MatrixXd mktrasp(Eigen::MatrixXd X const int n, const int p){
  Eigen::Matrix<double, p, n, RowMajor> T;
  T = X.transpose();
  return T;
}

Но я получаю ошибки компилятора

ошибка: 'p'не может появляться в константе-выраженииошибка: 'n' не может появляться в константном выражении

Я предполагаю, что это происходит потому, что n и p не известны во время компиляции.

Итак, я попробовал это решение

Eigen::MatrixXd mktrasp(Eigen::MatrixXd X, const int n, const int p){
  Eigen::Matrix<double, Dynamic, Dynamic, RowMajor> T(p, n);
  T = X.transpose();
  return T;
}

Это работает, но я полностью потерял сюжет.T - это динамическая матрица или фиксированный размер сейчас?Безопасно ли это делать?Может кто-нибудь предложить лучший подход?

1 Ответ

0 голосов
/ 21 мая 2018

Во многих случаях имеет смысл динамически распределять массивы / матрицы.В дополнение к преимуществу отсутствия чрезмерного использования памяти, я бы сказал, что самое большое преимущество заключается в том, что размеры матрицы распространяются через ваш код, поскольку это атрибут вашей матрицы.Для вашего примера вы можете в любой момент получить размеры по

A.rows(); // number of rows    (at runtime)
A.cols(); // number of columns (at runtime)
A.size(); // total size of the 'plain storage' (at runtime)

Теперь ваш пример становится таким же простым, как

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

typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> MatD;

MatD mktrasp(const MatD &X)
{
  return X.transpose();
}

int main()
{
  MatD A = MatD::Random(5,5);

  MatD B = mktrasp(A);

  std::cout << "A = " << std::endl << A << std::endl;
  std::cout << "B = " << std::endl << B << std::endl;
}

Если вы хотите работать с какой-то временной переменной, как показанов вашем примере вы также можете использовать:

MatD mktrasp(const MatD &X)
{
  // copies the transpose of "X" -> T
  // N.B. the dimensions (and possible other attributes) are also copied
  // you would thus find that "T.rows() == X.cols()"
  // (or if you would do "MatD A = X": "T.rows() == X.rows()")
  MatD T = X.transpose(); 

  return T;
}

Кстати, вы подошли очень близко, но вы слишком усложнили / переосмыслили.Во многих (почти во всех) случаях вы можете и должны избегать передачи размеров массива в C ++.Это делает ваш код более читабельным, более понятным и менее подверженным ошибкам.

...