模塊和頭文件
Eigen分爲一個核心模塊和幾個其他模塊。每個模塊都有一個相應的頭文件,必須包含該頭文件才能使用該模塊。The Dense
and Eigen
header files are provided to conveniently gain access to several modules at once.
模塊 | 頭文件 | 內容 |
---|---|---|
Core |
#include <Eigen/Core> |
Matrix 和 Array 類,基本的線性代數計算(including triangular and selfadjoint products),array 處理 |
Geometry |
#include <Eigen/Geometry> |
變換,平移,縮放,2D旋轉,3D旋轉(Quaternion, AngleAxis) |
LU |
#include <Eigen/LU> |
逆,行列式,LU 分解及求解器 (FullPivLU, PartialPivLU) |
Cholesky |
#include <Eigen/Cholesky> |
LLT and LDLT Cholesky分解及求解器 |
Householder |
#include <Eigen/Householder> |
Householder transformations;該模塊被多個線性代數計算庫使用 |
SVD |
#include <Eigen/SVD> |
SVD 分解及 最小二乘求解器 (JacobiSVD, BDCSVD) |
QR |
#include <Eigen/QR> |
QR 分解及其求解器with solver (HouseholderQR, ColPivHouseholderQR, FullPivHouseholderQR) |
Eigenvalues |
#include <Eigen/Eigenvalues> |
特徵值, 特徵向量分解(EigenSolver, SelfAdjointEigenSolver, ComplexEigenSolver) |
Sparse |
#include <Eigen/Sparse> |
稀疏矩陣存儲及其相關的線性代數計算(SparseMatrix, SparseVector) (see Quick reference guide for sparse matrices for details on sparse modules) |
#include <Eigen/Dense> |
包含了 Core, Geometry, LU, Cholesky, SVD, QR, and Eigenvalues 頭文件 | |
#include <Eigen/Eigen> |
包含了Dense and Sparse 頭文件 (整個 Eigen 庫) |
Array, matrix and vector 類型
Eigen提供了兩種Dense對象:均由模板類Matrix表示的數學矩陣和向量,and general 1D and 2D arrays represented by the template class Array:
typedef Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime, Options> MyMatrixType;
typedef Array<Scalar, RowsAtCompileTime, ColsAtCompileTime, Options> MyArrayType;
Scalar
is the scalar type of the coefficients (例如:float
,double
,bool
,int
等等).RowsAtCompileTime
和ColsAtCompileTime
是Matrix的行數和列數。Options
可以是ColMajor
或RowMajor
,默認值爲ColMajor
。(有關更多選項,請參見Matrix類)
允許所有組合:you can have a matrix with a fixed number of rows and a dynamic number of columns等等。
以下都是有效的:
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)
在大多數情況下, you can simply use one of the convenience typedefs for matrices and arrays. 一些例子:
矩陣 | 數組 |
---|---|
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
|
the matrix and array 的轉換:
Array44f a1, a1;
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);
- linear algebra matrix and vector only
- array objects only
基本矩陣運算
1D objects | 2D objects | Notes | |
---|---|---|---|
構造函數 |
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); |
By default, the coefficients are left uninitialized |
逗號初始化 |
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; |
|
逗號初始化 |
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; |
output:
|
|
運行時確定信息 |
vector.size(); vector.innerStride(); vector.data(); |
matrix.rows(); matrix.cols(); matrix.innerSize(); matrix.outerSize(); matrix.innerStride(); matrix.outerStride(); matrix.data(); |
Inner/Outer* are storage order dependent |
編譯時的信息 |
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); |
no-op if the new sizes match,
|
獲取元素 (範圍檢查) |
vector(i) vector.x() vector[i] vector.y() vector.z() vector.w() |
matrix(i,j) |
Range checking is disabled if
|
獲取元素 (沒有範圍檢查) |
vector.coeff(i) vector.coeffRef(i) |
matrix.coeff(i,j) matrix.coeffRef(i,j) |
|
賦值/複製 |
object = expression; object_of_float = expression_of_double.cast<float>(); |
the destination is automatically resized (if possible)
|
預定以矩陣
固定大小的矩陣或向量 | 動態大小的矩陣 | 動態大小的 vector |
---|---|---|
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 |
x = Dynamic2D::Identity(rows, cols); x.setIdentity(rows, cols); N/A |
N/A VectorXf::Unit(size,i) VectorXf::Unit(4,1) == Vector4f(0,1,0,0) == Vector4f::UnitY() |
Mapping external arrays
Contiguous memory |
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 |
Typical usage of strides |
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| |
數學運算符
add subtract |
mat3 = mat1 + mat2; mat3 += mat1; mat3 = mat1 - mat2; mat3 -= mat1; |
scalar product |
mat3 = mat1 * s1; mat3 *= s1; mat3 = s1 * mat1; mat3 = mat1 / s1; mat3 /= s1; |
matrix/vector products * |
col2 = mat1 * col1; row2 = row1 * mat1; row1 *= mat1; mat3 = mat1 * mat2; mat3 *= mat1; |
transposition adjoint * |
mat1 = mat2.transpose(); mat1.transposeInPlace(); mat1 = mat2.adjoint(); mat1.adjointInPlace(); |
dot product inner product * |
scalar = vec1.dot(vec2); scalar = col1.adjoint() * col2; scalar = (col1.adjoint() * col2).value(); |
outer product * |
mat = col1 * col2.transpose(); |
norm normalization * |
scalar = vec1.norm(); scalar = vec1.squaredNorm() vec2 = vec1.normalized(); vec1.normalize(); // inplace
|
cross product * |
#include <Eigen/Geometry> vec3 = vec1.cross(vec2); |
元素和數組運算符
除上述運算符外,Eigen supports numerous coefficient-wise operator and functions. 它們中的大多數在array-world *中明確地有意義。以下運算符很容易用於數組,或者可通過.array()用於向量和矩陣:
Arithmetic operators |
array1 * array2 array1 / array2 array1 *= array2 array1 /= array2 array1 + scalar array1 - scalar array1 += scalar array1 -= scalar |
Comparisons |
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) |
Trigo, power, and misc functions and the STL-like variants |
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 | STL-like APIs* | Comments |
---|---|---|
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 |
Some coefficient-wise operators 可用於 matrices and vectors 通過 cwise* methods:
Matrix API * | Via Array conversions |
---|---|
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之間的主要區別在於: the one based on cwise* methods returns an expression in the matrix world, while the second one (based on .array()) returns an array expression. 回想一下.array() 計算代價是沒有成本的,它僅更改可用的API和數據解釋。
It is also very simple to apply any user defined function foo
using DenseBase::unaryExpr together with std::ptr_fun (c++03), std::ref (c++11), or lambdas (c++11):
mat1.unaryExpr(std::ptr_fun(foo));
mat1.unaryExpr(std::ref(foo));
mat1.unaryExpr([](double x) { return foo(x); });
Reductions
Eigen 提供了reduction methods 如: minCoeff() , maxCoeff() , sum() , prod() , trace() *, norm() *, squaredNorm() *, all() , and any() .All reduction operations can be done matrix-wise, column-wise or row-wise .
用法:
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 |
Special versions of minCoeff and maxCoeff :
int i, j;
s = vector.minCoeff(&i); // s == vector[i]
s = matrix.maxCoeff(&i, &j); // s == matrix(i,j)
Typical use cases of all() and 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) ...
子矩陣
Read-write access to a column or a row of a matrix (or array):
mat1.row(i) = mat2.col(j);
mat1.col(j1).swap(mat1.col(j2));
Read-write access to sub-vectors:
Default versions | Optimized versions when the size is known at compile time |
|
---|---|---|
vec1.head(n) |
vec1.head<n>() |
the first n coeffs |
vec1.tail(n) |
vec1.tail<n>() |
the last n coeffs |
vec1.segment(pos,n) |
vec1.segment<n>(pos) |
the n coeffs in therange [ pos : pos + n - 1] |
Read-write access to sub-matrices: |
||
mat1.block(i,j,rows,cols) (more) |
mat1.block<rows,cols>(i,j) (more) |
the rows x cols sub-matrixstarting from position ( 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>() |
the rows x cols sub-matrixtaken in one of the four corners |
mat1.topRows(rows) mat1.bottomRows(rows) mat1.leftCols(cols) mat1.rightCols(cols) |
mat1.topRows<rows>() mat1.bottomRows<rows>() mat1.leftCols<cols>() mat1.rightCols<cols>() |
specialized versions of block() when the block fit two corners |
其他操作
Reverse
Vectors, rows, and/or columns of a matrix can be reversed (see DenseBase::reverse(), DenseBase::reverseInPlace(), VectorwiseOp::reverse()).
vec.reverse() mat.colwise().reverse() mat.rowwise().reverse()
vec.reverseInPlace()
複製
Vectors, matrices, rows, and/or columns can be replicated in any direction (see 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>()
對角, 三角化, and Self-adjoint matrices
對角矩陣
Operation | Code |
---|---|
view a vector as a diagonal matrix |
mat1 = vec1.asDiagonal(); |
Declare a diagonal matrix |
DiagonalMatrix<Scalar,SizeAtCompileTime> diag1(size); diag1.diagonal() = vector; |
Access the diagonal and super/sub diagonals of a matrix as a vector (read/write) |
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
|
Optimized products and inverse |
mat3 = scalar * diag1 * mat1; mat3 += scalar * mat1 * vec1.asDiagonal(); mat3 = vec1.asDiagonal().inverse() * mat1 mat3 = mat1 * diag1.inverse()
|
Triangular views
TriangularView 給出了密集矩陣的三角形部分的視圖,並允許對其執行優化的操作。The opposite triangular part is never referenced and can be used to store other information.
注意:The .triangularView() template member function requires the template
keyword if it is used on an object of a type that depends on a template parameter; 有關詳細信息,請參見C ++中的template和typename關鍵字。
Operation | Code |
---|---|
Reference to a triangular with optional unit or null diagonal (read/write): |
m.triangularView<Xxx>() Xxx = Upper, Lower, StrictlyUpper, StrictlyLower, UnitUpper, UnitLower |
Writing to a specific triangular part: (only the referenced triangular part is evaluated) |
m1.triangularView<Eigen::Lower>() = m2 + m3 |
Conversion to a dense matrix setting the opposite triangular part to zero: |
m2 = m1.triangularView<Eigen::UnitUpper>() |
Products: |
m3 += s1 * m1.adjoint().triangularView<Eigen::UnitUpper>() * m2 m3 -= s1 * m2.conjugate() * m1.adjoint().triangularView<Eigen::Lower>() |
L1.triangularView<Eigen::UnitLower>().solveInPlace(M2) L1.triangularView<Eigen::Lower>().adjoint().solveInPlace(M3) U1.triangularView<Eigen::Upper>().solveInPlace<OnTheRight>(M4) |
Symmetric/selfadjoint views
Just as for triangular matrix, 可以引用方矩陣的任何三角形部分以將其視爲自伴矩陣並執行特殊的優化操作。 Again the opposite triangular part is never referenced and can be used to store other information.
注意:The .selfadjointView() template member function requires the template
keyword if it is used on an object of a type that depends on a template parameter; 有關詳細信息,請參見C ++中的template和typename關鍵字。
Operation | Code |
---|---|
Conversion to a dense matrix: |
m2 = m.selfadjointView<Eigen::Lower>(); |
Product with another general matrix or vector: |
m3 = s1 * m1.conjugate().selfadjointView<Eigen::Upper>() * m3; m3 -= s1 * m3.adjoint() * m1.selfadjointView<Eigen::Lower>(); |
M1.selfadjointView<Eigen::Upper>().rankUpdate(M2,s1); M1.selfadjointView<Eigen::Lower>().rankUpdate(M2.adjoint(),-1); |
|
M.selfadjointView<Eigen::Upper>().rankUpdate(u,v,s); |
|
// 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); |