Быстрое справочное руководство
Модули и заголовочные файлы
Библиотека Eigen разделена на основной модуль и несколько дополнительных модулей. Каждый модуль имеет соответствующий заголовочный файл, который необходимо включить для использования модуля. Заголовочные файлы Dense и Eigen предоставляются для удобного доступа к нескольким модулям сразу.
| Модуль | Заголовочный файл | Содержимое |
|---|---|---|
| Основной | #include <Eigen/Core>
|
Классы Matrix и Array, основные операции линейной алгебры (включая треугольные и самосопряженные произведения), манипуляции с массивами |
| Геометрия | #include <Eigen/Geometry>
|
Transform, Translation, Масштабирование, Rotation2D и 3D вращения (Quaternion, AngleAxis) |
| LU | #include <Eigen/LU>
|
Inverse, определитель, LU-разложения с решением (FullPivLU, PartialPivLU) |
| Холецкого | #include <Eigen/Cholesky>
|
LLT и LDLT факторизация Холецкого с решением |
| Хаусхолдера | #include <Eigen/Householder>
|
Преобразования Хаусхолдера; этот модуль используется несколькими модулями линейной алгебры |
| SVD | #include <Eigen/SVD>
|
SVD-разложения с решением наименьших квадратов (JacobiSVD, BDCSVD) |
| QR | #include <Eigen/QR>
|
QR-разложение с решением (HouseholderQR, ColPivHouseholderQR, FullPivHouseholderQR) |
| Собственные значения | #include <Eigen/Eigenvalues>
|
Разложения собственных значений, собственных векторов (EigenSolver, SelfAdjointEigenSolver, ComplexEigenSolver) |
| Разреженный | #include <Eigen/Sparse>
|
Хранение разреженных матриц и связанные основные операции линейной алгебры (SparseMatrix, SparseVector) (см. Быстрое справочное руководство по разреженным матрицам для получения подробной информации о разреженных модулях) |
#include <Eigen/Dense>
|
Включает заголовочные файлы Core, Geometry, LU, Cholesky, SVD, QR и Eigenvalues | |
#include <Eigen/Eigen>
|
Включает заголовочные файлы Dense и Sparse (вся библиотека Eigen) |
Типы массивов, матриц и векторов
Обратите внимание: Библиотека Eigen предоставляет два типа плотных объектов: математические матрицы и векторы, которые оба представлены шаблоном класса Matrix, и общие 1D и 2D массивы, представленные шаблоном класса Array:
typedef Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime, Options> MyMatrixType; typedef Array<Scalar, RowsAtCompileTime, ColsAtCompileTime, Options> MyArrayType;
-
Scalar— тип скаляра коэффициентов (например,float,double,bool,int, и т.д.). -
RowsAtCompileTimeиColsAtCompileTime— количество строк и столбцов матрицы, известное на этапе компиляции, илиDynamic. -
Optionsможет бытьColMajorилиRowMajor, по умолчаниюColMajor. (см. класс Matrix для получения дополнительной информации)
Разрешены все комбинации: вы можете иметь матрицу с фиксированным числом строк и динамическим числом столбцов и т. д. Следующие варианты допустимы:
Matrix<double, 6, Dynamic> // Dynamic number of columns (heap allocation) Matrix<double, Dynamic, 2> // Dynamic number of rows (heap allocation) Matrix<double, Dynamic, Dynamic, RowMajor> // Fully dynamic, row major (heap allocation) Matrix<double, 13, 3> // Fully fixed (usually allocated on stack)
В большинстве случаев вы можете просто использовать один из удобных псевдонимов типов для матриц и массивов. Некоторые примеры:
| Матрицы | Массивы |
|---|---|
Matrix<float,Dynamic,Dynamic> <=> MatrixXf Matrix<double,Dynamic,1> <=> VectorXd Matrix<int,1,Dynamic> <=> RowVectorXi Matrix<float,3,3> <=> Matrix3f Matrix<float,4,1> <=> Vector4f |
Array<float,Dynamic,Dynamic> <=> ArrayXXf Array<double,Dynamic,1> <=> ArrayXd Array<int,1,Dynamic> <=> RowArrayXi Array<float,3,3> <=> Array33f Array<float,4,1> <=> Array4f |
Преобразование между мирами матриц и массивов:
Array44f a1, a2; Matrix4f m1, m2; m1 = a1 * a2; // coeffwise product, implicit conversion from array to matrix. a1 = m1 * m2; // matrix product, implicit conversion from matrix to array. a2 = a1 + m1.array(); // mixing array and matrix is forbidden m2 = a1.matrix() + m1; // and explicit conversion is required. ArrayWrapper<Matrix4f> m1a(m1); // m1a is an alias for m1.array(), they share the same coefficients MatrixWrapper<Array44f> a1m(a1);
В остальной части этого документа мы будем использовать следующие символы, чтобы подчеркнуть особенности, характерные для данного типа объекта:
Базовые манипуляции с матрицами
| 1D объекты | 2D объекты | Примечания | |
|---|---|---|---|
| Конструкторы | Vector4d v4;
Vector2f v1(x, y);
Array3i v2(x, y, z);
Vector4d v3(x, y, z, w);
VectorXf v5; // empty object
ArrayXf v6(size);
|
Matrix4f m1;
MatrixXf m5; // empty object
MatrixXf m6(nb_rows, nb_columns);
|
По умолчанию коэффициенты не инициализированы |
| Инициализатор запятыми | Vector3f v1; v1 << x, y, z; ArrayXf v2(4); v2 << 1, 2, 3, 4; |
Matrix3f m1; m1 << 1, 2, 3,
4, 5, 6,
7, 8, 9;
|
|
| Инициализатор запятыми (часть 2) |
int rows=5, cols=5; MatrixXf m(rows,cols); m << (Matrix3f() << 1, 2, 3, 4, 5, 6, 7, 8, 9).finished(), MatrixXf::Zero(3,cols-3), MatrixXf::Zero(rows-3,3), MatrixXf::Identity(rows-3,cols-3); cout << m; |
Вывод: 1 2 3 0 0 4 5 6 0 0 7 8 9 0 0 0 0 0 1 0 0 0 0 0 1 |
|
| Информация о времени выполнения | vector.size(); vector.innerStride(); vector.data(); |
matrix.rows(); matrix.cols(); matrix.innerSize(); matrix.outerSize(); matrix.innerStride(); matrix.outerStride(); matrix.data(); |
Внутренний/Внешний* зависят от порядка хранения |
| Информация о времени компиляции | ObjectType::Scalar ObjectType::RowsAtCompileTime ObjectType::RealScalar ObjectType::ColsAtCompileTime ObjectType::Index ObjectType::SizeAtCompileTime |
||
| Изменение размера | vector.resize(size); vector.resizeLike(other_vector); vector.conservativeResize(size); |
matrix.resize(nb_rows, nb_cols); matrix.resize(Eigen::NoChange, nb_cols); matrix.resize(nb_rows, Eigen::NoChange); matrix.resizeLike(other_matrix); matrix.conservativeResize(nb_rows, nb_cols); |
безоперационное действие, если новые размеры совпадают, иначе данные теряются |
| Доступ к коэффициентам с проверкой диапазона | vector(i) vector.x()
vector[i] vector.y()
vector.z()
vector.w()
|
matrix(i,j) |
Проверка диапазона отключена, если определены NDEBUG или EIGEN_NO_DEBUG |
| Доступ к коэффициентам без проверки диапазона | vector.coeff(i) vector.coeffRef(i) |
matrix.coeff(i,j) matrix.coeffRef(i,j) |
|
| Присваивание/копирование | object = expression; object_of_float = expression_of_double.cast<float>(); |
назначение автоматически изменяет размер назначения (если возможно) |
|
Предопределённые матрицы
| Матрица или вектор фиксированного размера | Матрица динамического размера | Вектор динамического размера |
|---|---|---|
typedef {Matrix3f|Array33f} FixedXD;
FixedXD x;
x = FixedXD::Zero();
x = FixedXD::Ones();
x = FixedXD::Constant(value);
x = FixedXD::Random();
x = FixedXD::LinSpaced(size, low, high);
x.setZero();
x.setOnes();
x.setConstant(value);
x.setRandom();
x.setLinSpaced(size, low, high);
|
typedef {MatrixXf|ArrayXXf} Dynamic2D;
Dynamic2D x;
x = Dynamic2D::Zero(rows, cols);
x = Dynamic2D::Ones(rows, cols);
x = Dynamic2D::Constant(rows, cols, value);
x = Dynamic2D::Random(rows, cols);
N/A
x.setZero(rows, cols);
x.setOnes(rows, cols);
x.setConstant(rows, cols, value);
x.setRandom(rows, cols);
N/A
|
typedef {VectorXf|ArrayXf} Dynamic1D;
Dynamic1D x;
x = Dynamic1D::Zero(size);
x = Dynamic1D::Ones(size);
x = Dynamic1D::Constant(size, value);
x = Dynamic1D::Random(size);
x = Dynamic1D::LinSpaced(size, low, high);
x.setZero(size);
x.setOnes(size);
x.setConstant(size, value);
x.setRandom(size);
x.setLinSpaced(size, low, high);
|
| Единичная и базисные векторы * | ||
x = FixedXD::Identity(); x.setIdentity(); Vector3f::UnitX() // 1 0 0 Vector3f::UnitY() // 0 1 0 Vector3f::UnitZ() // 0 0 1 Vector4f::Unit(i) x.setUnit(i); |
x = Dynamic2D::Identity(rows, cols); x.setIdentity(rows, cols); N/A |
N/A VectorXf::Unit(size,i) x.setUnit(size,i); VectorXf::Unit(4,1) == Vector4f(0,1,0,0) == Vector4f::UnitY() |
Обратите внимание, что разрешено вызывать любую из функций set* для вектора или матрицы динамического размера без передачи новых размеров. Например:
MatrixXi M(3,3); M.setIdentity();
Картирование внешних массивов
| Непрерывное хранилище памяти |
float data[] = {1,2,3,4}; Map<Vector3f> v1(data); // uses v1 as a Vector3f object Map<ArrayXf> v2(data,3); // uses v2 as a ArrayXf object Map<Array22f> m1(data); // uses m1 as a Array22f object Map<MatrixXf> m2(data,2,2); // uses m2 as a MatrixXf object |
| Типичное использование шагов |
float data[] = {1,2,3,4,5,6,7,8,9}; Map<VectorXf,0,InnerStride<2> > v1(data,3); // = [1,3,5] Map<VectorXf,0,InnerStride<> > v2(data,3,InnerStride<>(3)); // = [1,4,7] Map<MatrixXf,0,OuterStride<3> > m2(data,2,3); // both lines |1,4,7| Map<MatrixXf,0,OuterStride<> > m1(data,2,3,OuterStride<>(3)); // are equal to: |2,5,8| |
Арифметические операторы
| Сложение Вычитание |
mat3 = mat1 + mat2; mat3 += mat1; mat3 = mat1 - mat2; mat3 -= mat1; |
| Произведение скаляра |
mat3 = mat1 * s1; mat3 *= s1; mat3 = s1 * mat1; mat3 = mat1 / s1; mat3 /= s1; |
| Произведение матрицы/вектора * |
col2 = mat1 * col1; row2 = row1 * mat1; row1 *= mat1; mat3 = mat1 * mat2; mat3 *= mat1; |
| Транспонирование сопряжение * |
mat1 = mat2.transpose(); mat1.transposeInPlace(); mat1 = mat2.adjoint(); mat1.adjointInPlace(); |
|
Точечное произведение внутреннее произведение * |
scalar = vec1.dot(vec2); scalar = col1.adjoint() * col2; scalar = (col1.adjoint() * col2).value(); |
| ВнЕшнЕЕ произведение * |
mat = col1 * col2.transpose(); |
|
Норма Нормализация * |
scalar = vec1.norm(); scalar = vec1.squaredNorm()
vec2 = vec1.normalized(); vec1.normalize(); // inplace
|
| Векторное произведение * |
#include <Eigen/Geometry>
vec3 = vec1.cross(vec2);
|
Операции по коэффициентам & массивы
Помимо вышеупомянутых операторов, Eigen поддерживает множество операторов и функций поэлементного применения. Большинство из них однозначно интерпретируются в мире массивов*. Следующие операторы доступны для массивов, или доступны через .array() для векторов и матриц:
| Арифметические операторы |
array1 * array2 array1 / array2 array1 *= array2 array1 /= array2 array1 + scalar array1 - scalar array1 += scalar array1 -= scalar |
| Сравнения |
array1 < array2 array1 > array2 array1 < scalar array1 > scalar array1 <= array2 array1 >= array2 array1 <= scalar array1 >= scalar array1 == array2 array1 != array2 array1 == scalar array1 != scalar array1.min(array2) array1.max(array2) array1.min(scalar) array1.max(scalar) |
| Тригонометрические, степенные и смешанные функции и аналоги STL |
array1.abs2() array1.abs() abs(array1) array1.sqrt() sqrt(array1) array1.log() log(array1) array1.log10() log10(array1) array1.exp() exp(array1) array1.pow(array2) pow(array1,array2) array1.pow(scalar) pow(array1,scalar) pow(scalar,array2) array1.square() array1.cube() array1.inverse() array1.sin() sin(array1) array1.cos() cos(array1) array1.tan() tan(array1) array1.asin() asin(array1) array1.acos() acos(array1) array1.atan() atan(array1) array1.sinh() sinh(array1) array1.cosh() cosh(array1) array1.tanh() tanh(array1) array1.arg() arg(array1) array1.floor() floor(array1) array1.ceil() ceil(array1) array1.round() round(aray1) array1.isFinite() isfinite(array1) array1.isInf() isinf(array1) array1.isNaN() isnan(array1) |
Следующие операторы поэлементного применения доступны для всех типов выражений (матрицы, векторы и массивы), а также для вещественных и комплексных типов скаляров:
| Eigen's API | API в стиле STL* | Комментарии |
|---|---|---|
mat1.real() mat1.imag() mat1.conjugate() |
real(array1) imag(array1) conj(array1) |
// read-write, no-op for real expressions // read-only for real, read-write for complexes // no-op for real expressions |
Некоторые операторы поэлементного применения доступны для матриц и векторов через следующие методы cwise*:
| Матрица API * | Через преобразования в Массив |
|---|---|
mat1.cwiseMin(mat2) mat1.cwiseMin(scalar) mat1.cwiseMax(mat2) mat1.cwiseMax(scalar) mat1.cwiseAbs2() mat1.cwiseAbs() mat1.cwiseSqrt() mat1.cwiseInverse() mat1.cwiseProduct(mat2) mat1.cwiseQuotient(mat2) mat1.cwiseEqual(mat2) mat1.cwiseEqual(scalar) mat1.cwiseNotEqual(mat2) |
mat1.array().min(mat2.array()) mat1.array().min(scalar) mat1.array().max(mat2.array()) mat1.array().max(scalar) mat1.array().abs2() mat1.array().abs() mat1.array().sqrt() mat1.array().inverse() mat1.array() * mat2.array() mat1.array() / mat2.array() mat1.array() == mat2.array() mat1.array() == scalar mat1.array() != mat2.array() |
Основное различие между двумя API заключается в том, что API, основанное на методах cwise*, возвращает выражение в мире матриц, в то время как второе API (основанное на .array()) возвращает выражение массива. Обратите внимание, что .array() не имеет затрат, оно только изменяет доступное API и интерпретацию данных.
Также очень просто применить любую пользовательскую функцию foo с помощью DenseBase::unaryExpr вместе с std::ptr_fun (c++03, устарело или удалено в более новых версиях C++), std::ref (c++11) или лямбда-выражениями (c++11):
mat1.unaryExpr(std::ptr_fun(foo)); mat1.unaryExpr(std::ref(foo)); mat1.unaryExpr([](double x) { return foo(x); });
Обратите внимание, что передать указатель на обычную функцию напрямую в unaryExpr нельзя, поэтому её необходимо обернуть, как показано выше.
Сводные операции
Eigen предоставляет несколько методов сводки, таких как: minCoeff() , maxCoeff() , sum() , prod() , trace() *, norm() *, squaredNorm() *, all() и any() . Все операции сводки могут быть выполнены по матрице, столбцу или строке . Пример использования:
5 3 1
mat = 2 7 8
9 4 6
|
mat.minCoeff(); |
1 |
mat.colwise().minCoeff(); |
2 3 1 |
|
mat.rowwise().minCoeff(); |
1 2 4 |
Специальные версии minCoeff и maxCoeff :
int i, j; s = vector.minCoeff(&i); // s == vector[i] s = matrix.maxCoeff(&i, &j); // s == matrix(i,j)
Типичные случаи использования all() и any():
if((array1 > 0).all()) ... // if all coefficients of array1 are greater than 0 ... if((array1 < array2).any()) ... // if there exist a pair i,j such that array1(i,j) < array2(i,j) ...
Подматрицы
Чтение и запись столбца или строки матрицы (или массива):
mat1.row(i) = mat2.col(j); mat1.col(j1).swap(mat1.col(j2));
Чтение и запись подвекторов:
| Стандартные версии | Оптимизированные версии, когда размер известен на этапе компиляции |
|
|---|---|---|
vec1.head(n) |
vec1.head<n>() |
первые n коэффициенты |
vec1.tail(n) |
vec1.tail<n>() |
последние n коэффициенты |
vec1.segment(pos,n) |
vec1.segment<n>(pos) |
коэффициенты в диапазоне [ pos : pos + n - 1] |
|
Чтение и запись подматриц: |
||
mat1.block(i,j,rows,cols)(ещё) |
mat1.block<rows,cols>(i,j)(ещё) |
подматрица rows x cols начиная с позиции ( i,j) |
mat1.topLeftCorner(rows,cols) mat1.topRightCorner(rows,cols) mat1.bottomLeftCorner(rows,cols) mat1.bottomRightCorner(rows,cols) |
mat1.topLeftCorner<rows,cols>() mat1.topRightCorner<rows,cols>() mat1.bottomLeftCorner<rows,cols>() mat1.bottomRightCorner<rows,cols>() |
подматрица rows x cols взятая в одном из четырёх углов |
mat1.topRows(rows) mat1.bottomRows(rows) mat1.leftCols(cols) mat1.rightCols(cols) |
mat1.topRows<rows>() mat1.bottomRows<rows>() mat1.leftCols<cols>() mat1.rightCols<cols>() |
специализированные версии block() когда блок соответствует двум углам |
Разные операции
Обращение
Векторы, строки и/или столбцы матрицы могут быть обращены (см. DenseBase::reverse(), DenseBase::reverseInPlace(), VectorwiseOp::reverse()).
vec.reverse() mat.colwise().reverse() mat.rowwise().reverse() vec.reverseInPlace()
Дублирование
Векторы, матрицы, строки и/или столбцы могут быть продублированы в любом направлении (см. DenseBase::replicate(), VectorwiseOp::replicate())
vec.replicate(times) vec.replicate<Times> mat.replicate(vertical_times, horizontal_times) mat.replicate<VerticalTimes, HorizontalTimes>() mat.colwise().replicate(vertical_times, horizontal_times) mat.colwise().replicate<VerticalTimes, HorizontalTimes>() mat.rowwise().replicate(vertical_times, horizontal_times) mat.rowwise().replicate<VerticalTimes, HorizontalTimes>()
Диагональные, треугольные и самосопряженные матрицы
(мир матриц *)
Диагональные матрицы
| Операция | Код |
|---|---|
| представление вектора в виде диагональной матрицы |
mat1 = vec1.asDiagonal(); |
| Объявление диагональной матрицы |
DiagonalMatrix<Scalar,SizeAtCompileTime> diag1(size); diag1.diagonal() = vector; |
| Доступ к диагонали и над/поддиагоналям матрицы как к вектору (чтение/запись) |
vec1 = mat1.diagonal(); mat1.diagonal() = vec1; // main diagonal vec1 = mat1.diagonal(+n); mat1.diagonal(+n) = vec1; // n-th super diagonal vec1 = mat1.diagonal(-n); mat1.diagonal(-n) = vec1; // n-th sub diagonal vec1 = mat1.diagonal<1>(); mat1.diagonal<1>() = vec1; // first super diagonal vec1 = mat1.diagonal<-2>(); mat1.diagonal<-2>() = vec1; // second sub diagonal |
| Оптимизированные произведения и обращение |
mat3 = scalar * diag1 * mat1; mat3 += scalar * mat1 * vec1.asDiagonal(); mat3 = vec1.asDiagonal().inverse() * mat1 mat3 = mat1 * diag1.inverse() |
Треугольные представления
TriangularView предоставляет представление треугольной части плотной матрицы и позволяет выполнять оптимизированные операции с ней. Противоположная треугольная часть никогда не ссылается и может использоваться для хранения другой информации.
- Примечание
- Шаблонный член-функция .triangularView() требует ключевое слово
template, если используется с объектом, тип которого зависит от шаблона; см. Ключевые слова template и typename в C++ для получения подробностей.
| Операция | Код |
|---|---|
| Ссылка на треугольную часть с необязательной единичной или нулевой диагональю (чтение/запись): |
m.triangularView<Xxx>() Xxx = Upper, Lower, StrictlyUpper, StrictlyLower, UnitUpper, UnitLower |
| Запись в определённую треугольную часть: (только указанная треугольная часть оценивается) |
m1.triangularView<Eigen::Lower>() = m2 + m3 |
| Преобразование в плотную матрицу с обнулением противоположной треугольной части: |
m2 = m1.triangularView<Eigen::UnitUpper>() |
| Произведения: |
m3 += s1 * m1.adjoint().triangularView<Eigen::UnitUpper>() * m2 m3 -= s1 * m2.conjugate() * m1.adjoint().triangularView<Eigen::Lower>() |
| Решение линейных уравнений: \( M_2 := L_1^{-1} M_2 \) \( M_3 := {L_1^*}^{-1} M_3 \) \( M_4 := M_4 U_1^{-1} \) |
L1.triangularView<Eigen::UnitLower>().solveInPlace(M2) L1.triangularView<Eigen::Lower>().adjoint().solveInPlace(M3) U1.triangularView<Eigen::Upper>().solveInPlace<OnTheRight>(M4) |
Симметричные/самосопряжённые представления
Так же, как и для треугольных матриц, вы можете ссылаться на любую треугольную часть квадратной матрицы, чтобы рассматривать её как самосопряжённую и выполнять специальные и оптимизированные операции. Опять же, противоположная треугольная часть никогда не ссылается и может использоваться для хранения другой информации.
- Примечание
- Шаблонный член-функция .selfadjointView() требует ключевое слово
template, если используется с объектом, тип которого зависит от шаблона; см. Ключевые слова template и typename в C++ для получения подробностей.
| Операция | Код |
|---|---|
| Преобразование в плотную матрицу: |
m2 = m.selfadjointView<Eigen::Lower>(); |
| Произведение с другой общей матрицей или вектором: |
m3 = s1 * m1.conjugate().selfadjointView<Eigen::Upper>() * m3; m3 -= s1 * m3.adjoint() * m1.selfadjointView<Eigen::Lower>(); |
| Обновление ранга 1 и ранга K: \( upper(M_1) \mathrel{{+}{=}} s_1 M_2 M_2^* \) \( lower(M_1) \mathbin{{-}{=}} M_2^* M_2 \) |
M1.selfadjointView<Eigen::Upper>().rankUpdate(M2,s1); M1.selfadjointView<Eigen::Lower>().rankUpdate(M2.adjoint(),-1); |
| Обновление ранга 2: ( \( M \mathrel{{+}{=}} s u v^* + s v u^* \)) |
M.selfadjointView<Eigen::Upper>().rankUpdate(u,v,s); |
| Решение линейных уравнений: ( \( M_2 := M_1^{-1} M_2 \)) |
// via a standard Cholesky factorization m2 = m1.selfadjointView<Eigen::Upper>().llt().solve(m2); // via a Cholesky factorization with pivoting m2 = m1.selfadjointView<Eigen::Lower>().ldlt().solve(m2); |
© Eigen.
Licensed under the MPL2 License.
https://eigen.tuxfamily.org/dox/group__QuickRefPage.html