Eigen是可以用來進行線性代數、矩陣、向量操作等運算的C++庫,它里面包含了很多算法。它的License是MPL2。它支持多平台。
Eigen采用源碼的方式提供給用戶使用,在使用時只需要包含Eigen的頭文件即可進行使用。之所以采用這種方式,是因為Eigen采用模板方式實現,由於模板函數不支持分離編譯,所以只能提供源碼而不是動態庫的方式供用戶使用。
矩陣的定義:Eigen中關於矩陣類的模板函數中,共有六個模板參數,常用的只有前三個。其前三個參數分別表示矩陣元素的類型、行數和列數。
矩陣定義時可以使用Dynamic來表示矩陣的行列數為未知。
Eigen中無論是矩陣還是數組、向量,無論是靜態矩陣還是動態矩陣都提供默認構造函數,也就是定義這些數據結構時都可以不用提供任何參數,其大小均由運行時來確定。矩陣的構造函數中只提供行列數、元素類型的構造參數,而不提供元素值的構造,對於比較小的、固定長度的向量提供初始化元素的定義。
矩陣類型:Eigen中的矩陣類型一般都是用類似MatrixXXX來表示,可以根據該名字來判斷其數據類型,比如”d”表示double類型,”f”表示float類型,”i”表示整數,”c”表示復數;Matrix2f,表示的是一個2*2維的,其每個元素都是float類型。
數據存儲:Matrix創建的矩陣默認是按列存儲,Eigen在處理按列存儲的矩陣時會更加高效。如果想修改可以在創建矩陣的時候加入參數,如:
Matrix<int,3, 4, ColMajor> Acolmajor;
Matrix<int,3, 4, RowMajor> Arowmajor;
動態矩陣和靜態矩陣:動態矩陣是指其大小在運行時確定,靜態矩陣是指其大小在編譯時確定。
MatrixXd:表示任意大小的元素類型為double的矩陣變量,其大小只有在運行時被賦值之后才能知道。
Matrix3d:表示元素類型為double大小為3*3的矩陣變量,其大小在編譯時就知道。
在Eigen中行優先的矩陣會在其名字中包含有row,否則就是列優先。
Eigen中的向量只是一個特殊的矩陣,其維度為1而已。
矩陣元素的訪問:在矩陣的訪問中,行索引總是作為第一個參數,Eigen中矩陣、數組、向量的下標都是從0開始。矩陣元素的訪問可以通過”()”操作符完成。例如m(2, 3)既是獲取矩陣m的第2行第3列元素。
針對向量還提供”[]”操作符,注意矩陣則不可如此使用。
設置矩陣的元素:在Eigen中重載了”<<”操作符,通過該操作符即可以一個一個元素的進行賦值,也可以一塊一塊的賦值。另外也可以使用下標進行賦值。
重置矩陣大小:當前矩陣的行數、列數、大小可以通過rows()、cols()和size()來獲取,對於動態矩陣可以通過resize()函數來動態修改矩陣的大小。注意:(1)、固定大小的矩陣是不能使用resize()來修改矩陣的大小;(2)、resize()函數會析構掉原來的數據,因此調用resize()函數之后將不能保證元素的值不改變;(3)、使用”=”操作符操作動態矩陣時,如果左右兩邊的矩陣大小不等,則左邊的動態矩陣的大小會被修改為右邊的大小。
如何選擇動態矩陣和靜態矩陣:對於小矩陣(一般大小小於16)使用固定大小的靜態矩陣,它可以帶來比較高的效率;對於大矩陣(一般大小大於32)建議使用動態矩陣。注意:如果特別大的矩陣使用了固定大小的靜態矩陣則可能會造成棧溢出的問題。
矩陣和向量的算術運算:在Eigen中算術運算重載了C++的+、-、*
(1)、矩陣的運算:提供+、-、一元操作符”-”、+=、-=;二元操作符+/-,表示兩矩陣相加(矩陣中對應元素相加/減,返回一個臨時矩陣);一元操作符-表示對矩陣取負(矩陣中對應元素取負,返回一個臨時矩陣);組合操作法+=或者-=表示(對應每個元素都做相應操作);矩陣還提供與標量(單一數字)的乘除操作,表示每個元素都與該標量進行乘除操作;
(2)、求矩陣的轉置、共軛矩陣、伴隨矩陣:可以通過成員函數transpose()、conjugate()、adjoint()來完成。注意:這些函數返回操作后的結果,而不會對原矩陣的元素進行直接操作,如果要讓原矩陣進行轉換,則需要使用響應的InPlace函數,如transpoceInPlace()等;
(3)、矩陣相乘、矩陣向量相乘:使用操作符*,共有*和*=兩種操作符;
(4)、矩陣的塊操作:有兩種使用方法:
matrix.block(i,j, p, q) : 表示返回從矩陣(i, j)開始,每行取p個元素,每列取q個元素所組成的臨時新矩陣對象,原矩陣的元素不變;
matrix.block<p,q>(i, j) :<p, q>可理解為一個p行q列的子矩陣,該定義表示從原矩陣中第(i, j)開始,獲取一個p行q列的子矩陣,返回該子矩陣組成的臨時矩陣對象,原矩陣的元素不變;
(5)、向量的塊操作:
獲取向量的前n個元素:vector.head(n);
獲取向量尾部的n個元素:vector.tail(n);
獲取從向量的第i個元素開始的n個元素:vector.segment(i,n);
Map類:在已經存在的矩陣或向量中,不必拷貝對象,而是直接在該對象的內存上進行運算操作。
1. 從http://eigen.tuxfamily.org/index.php?title=Main_Page下載最新穩定版本3.2.5,解壓縮;
2. 新建一個vs2013 TestEigen控制台工程,將Eigen文件所在目錄加入到工程屬性的C/C++附加包含目錄中,這樣就可以使用Eigen中的函數了;
3. TestEigen.cpp文件中的內容為:
- #include "stdafx.h"
- #include <iostream>
- #include <Eigen/Dense>
- template <typename T>
- static void matrix_mul_matrix(T* p1, int iRow1, int iCol1, T* p2, int iRow2, int iCol2, T* p3)
- {
- if (iRow1 != iRow2) return;
- //列優先
- //Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> > map1(p1, iRow1, iCol1);
- //Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> > map2(p2, iRow2, iCol2);
- //Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> > map3(p3, iCol1, iCol2);
- //行優先
- Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > map1(p1, iRow1, iCol1);
- Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > map2(p2, iRow2, iCol2);
- Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > map3(p3, iCol1, iCol2);
- map3 = map1 * map2;
- }
- int main(int argc, char* argv[])
- {
- //1. 矩陣的定義
- Eigen::MatrixXd m(2, 2);
- Eigen::Vector3d vec3d;
- Eigen::Vector4d vec4d(1.0, 2.0, 3.0, 4.0);
- //2. 動態矩陣、靜態矩陣
- Eigen::MatrixXd matrixXd;
- Eigen::Matrix3d matrix3d;
- //3. 矩陣元素的訪問
- m(0, 0) = 1;
- m(0, 1) = 2;
- m(1, 0) = m(0, 0) + 3;
- m(1, 1) = m(0, 0) * m(0, 1);
- std::cout << m << std::endl << std::endl;
- //4. 設置矩陣的元素
- m << -1.5, 2.4,
- 6.7, 2.0;
- std::cout << m << std::endl << std::endl;
- int row = 4;
- int col = 5;
- Eigen::MatrixXf matrixXf(row, col);
- matrixXf << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20;
- std::cout << matrixXf << std::endl << std::endl;
- matrixXf << Eigen::MatrixXf::Identity(row, col);
- std::cout << matrixXf << std::endl << std::endl;
- //5. 重置矩陣大小
- Eigen::MatrixXd matrixXd1(3, 3);
- m = matrixXd1;
- std::cout << m.rows() << " " << m.cols() << std::endl << std::endl;
- //6. 矩陣運算
- m << 1, 2, 7,
- 3, 4, 8,
- 5, 6, 9;
- std::cout << m << std::endl;
- matrixXd1 = Eigen::Matrix3d::Random();
- m += matrixXd1;
- std::cout << m << std::endl << std::endl;
- m *= 2;
- std::cout << m << std::endl << std::endl;
- std::cout << -m << std::endl << std::endl;
- std::cout << m << std::endl << std::endl;
- //7. 求矩陣的轉置、共軛矩陣、伴隨矩陣
- std::cout << m.transpose() << std::endl << std::endl;
- std::cout << m.conjugate() << std::endl << std::endl;
- std::cout << m.adjoint() << std::endl << std::endl;
- std::cout << m << std::endl << std::endl;
- m.transposeInPlace();
- std::cout << m << std::endl << std::endl;
- //8. 矩陣相乘、矩陣向量相乘
- std::cout << m*m << std::endl << std::endl;
- vec3d = Eigen::Vector3d(1, 2, 3);
- std::cout << m * vec3d << std::endl << std::endl;
- std::cout << vec3d.transpose()*m << std::endl << std::endl;
- //9. 矩陣的塊操作
- std::cout << m << std::endl << std::endl;
- std::cout << m.block(1, 1, 2, 2) << std::endl << std::endl;
- std::cout << m.block<1, 2>(0, 0) << std::endl << std::endl;
- std::cout << m.col(1) << std::endl << std::endl;
- std::cout << m.row(0) << std::endl << std::endl;
- //10. 向量的塊操作
- Eigen::ArrayXf arrayXf(10);
- arrayXf << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
- std::cout << vec3d << std::endl << std::endl;
- std::cout << arrayXf << std::endl << std::endl;
- std::cout << arrayXf.head(5) << std::endl << std::endl;
- std::cout << arrayXf.tail(4) * 2 << std::endl << std::endl;
- //11. 求解矩陣的特征值和特征向量
- Eigen::Matrix2f matrix2f;
- matrix2f << 1, 2, 3, 4;
- Eigen::SelfAdjointEigenSolver<Eigen::Matrix2f> eigenSolver(matrix2f);
- if (eigenSolver.info() == Eigen::Success) {
- std::cout << eigenSolver.eigenvalues() << std::endl << std::endl;
- std::cout << eigenSolver.eigenvectors() << std::endl << std::endl;
- }
- //12. 類Map及動態矩陣的使用
- int array1[4] = { 1, 2, 3, 4 };
- int array2[4] = { 5, 6, 7, 8 };
- int array3[4] = { 0, 0, 0, 0};
- matrix_mul_matrix(array1, 2, 2, array2, 2, 2, array3);
- for (int i = 0; i < 4; i++)
- std::cout << array3[i] << std::endl;
- return 0;
- }
參考文獻:
1. http://blog.csdn.net/augusdi/article/details/12907341
2. http://www.docin.com/p-863098431.html
3. http://www.360doc.com/content/15/0325/15/21172899_457946100.shtml
4. http://www.360doc.com/content/15/0413/22/21172899_463003614.shtml