Eigen 3.3.7 入門教程
原文地址:http://eigen.tuxfamily.org/dox/GettingStarted.html
學完當前教程后可以參考 The Matrix class 進行進一步學習。
如何安裝 Eigen
因為 Eigen 是 header-only 的,所以直接下載 Eigen 頭文件即可使用。
一個簡單的示例
#include <iostream>
#include <Eigen/Dense>
using Eigen::MatrixXd;
int main()
{
MatrixXd m(2,2);
m(0,0) = 3;
m(1,0) = 2.5;
m(0,1) = -1;
m(1,1) = m(1,0) + m(0,1);
std::cout << m << std::endl;
}
下面先介紹編譯方式再解釋代碼
編譯並執行
Eigen 不依賴其他三方庫,只要把 Eigen 庫放到編譯器可以發現的路徑即可。使用GCC你可以使用-I
指明Eigen頭文件的路徑,你可以使用下面的指令編譯上面的代碼:
g++ -I /path/to/eigen/ my_program.cpp -o my_program
在linux或者Mac OS X中,你可以將 Eigen 頭文件復制到 usr/local/include
目錄下,這樣你就可以使用下面的指令編譯上面的代碼:
g++ my_program.cpp -o my_program
編譯並執行上面的代碼,你將獲得如下輸出:
3 -1 2.5 1.5
解釋第一個程序
Eigen 頭文件定義了很多類型,對於簡單的使用來說只使用 MatrixXd 類就可以了。MatrixXd 可以表示任意維度的矩陣(MatrixXd中的X表示任意),而且矩陣的元素都是 double 類型的(MatrixXd中的d表示double)。quick reference guide 中簡要介紹了 Eigen 提供的用於描述矩陣的類。
Eigen/Dense頭文件定義了MatrixXd類中可用的所有方法和相關類型,所有方法均定義在Eigen名字空間中。
main 函數中的第一行定義了一個2行2列的MatrixXd矩陣,表達式m(0,0) = 3
將矩陣左上角的元素置為3。在 Eigen 中你可以使用小括號來獲得對應元素的引用。在計算機科學中第一個元素的下標為 0,然而在傳統的數學表達方法中第一個元素的下標是 1。
示例2,:矩陣和向量
下面的例子包含了矩陣和向量,我們先講第二段代碼
// 代碼片段1:運行時設置矩陣的維度
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
int main()
{
MatrixXd m = MatrixXd::Random(3,3);
m = (m + MatrixXd::Constant(3,3,1.2)) * 50;
cout << "m =" << endl << m << endl;
VectorXd v(3);
v << 1, 2, 3;
cout << "m * v =" << endl << m * v << endl;
}
// 代碼片段2:編譯時確定矩陣的維度
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
int main()
{
Matrix3d m = Matrix3d::Random();
m = (m + Matrix3d::Constant(1.2)) * 50;
cout << "m =" << endl << m << endl;
Vector3d v(1,2,3);
cout << "m * v =" << endl << m * v << endl;
}
第二段代碼編譯后執行的輸出為(因為矩陣是隨機初始化的故輸出可能不同):
m =
10.1251 90.8741 45.0291
66.3585 68.5009 99.5962
29.3304 57.9873 92.284
m * v =
326.961
502.149
422.157
第二個示例的解釋
第二段代碼main中聲明了一個3×3的矩陣並使用 Random() 進行了隨機初始化(初始值在-1和1之間)。第二行代碼將m中所有元素的值映射到10和110之間。Constant(3,3,1.2)生成了一個所有元素值為1.2的3×3的矩陣。第三行引入了一個新的類型:VectorXd,這個類表示了一個任意維度列向量。第四行代碼使用逗號初始化生成了一個3×1的向量。
最后一行代碼執行矩陣和向量的點乘。
上面示例中的兩段代碼,其功能是相同的。第一段代碼使用的向量和矩陣其維度是在運行時決定的,第二段代碼中矩陣和向量的形狀在編譯時就已知了,第二段代碼中矩陣和向量的維度是固定的。
使用固定尺寸的矩陣有一定的優勢,例如編譯器可以生成更高效的可執行文件。使用固定尺寸的類型可以進行更加嚴格的編譯時檢查,例如編譯器可以檢查兩個向量是否可以相乘。一個比較好的經驗是在矩陣維度小於或等於 4×4 時使用固定尺寸的矩陣(例如:Matrix3f、Matrix2i、Matrix4d等內置類型)。
進一步的學習
閱讀long turorial是比較好的選擇。
其他教程
下面內容源自CSCI2240
使用模板創建固定維度的矩陣
Matrix<short, 5, 5> m1;
Matrix<float, 20, 75> m2;
使用模板創建未知維度的矩陣
// MatrixXf, MatrixXd
迭代矩陣
Eigen 在內存中按列順序保存矩陣,所以在迭代矩陣的時候按列的順序進行迭代,效率會比按行進行迭代要快(逗號初始化的時候按行),如下偽代碼:
for i = 1:4 {
for j = 1:4 {
B(j , i ) = 0.0;
}
}
內置矩陣輔助函數
// Set each coefficient to a uniform random value in the range [ -1 , 1]
A = Matrix3f :: Random () ;
// Set B to the identity matrix
B = Matrix4d :: Identity () ;
// Set all elements to zero
A = Matrix3f :: Zero () ;
// Set all elements to ones
A = Matrix3f :: Ones () ;
// Set all elements to a constant value
B = Matrix4d :: Constant (4.5) ;
// Scalar multiplication , and subtraction
// What do you expect the output to be?
cout << M2 - Matrix4f :: Ones () * 2.2 << endl ;
將矩陣看做數組
一些對矩陣的運算需要操作每一個矩陣元素,使用 array()
方法可以讓 Eigen 將矩陣看做數組,隨后的操作都將是 element-wise(以元素為單位進行處理)。array()
不是in-place操作,即 array() 將返回一個和原矩陣完全相同的新矩陣對象。為了效率,Eigen 沒有為Matrix類提供element-wise操作,做這些操作需要先將矩陣轉化為Array對象,所以自己寫代碼時要先確定需要哪種對象來完成操作。
// Square each element of the matrix
cout << M1 . array () . square () << endl ;
// Multiply two matrices element - wise
cout << M1 . array () * Matrix4f :: Identity () . array () << endl ;
// All relational operators can be applied element - wise
cout << M1 . array () <= M2 . array () << endl << endl ;
cout << M1 . array () > M2 . array () << endl ;
向量
// Utility functions
Vector3f v1 = Vector3f :: Ones () ;
Vector3f v2 = Vector3f :: Zero () ;
Vector4d v3 = Vector4d :: Random () ;
Vector4d v4 = Vector4d :: Constant (1.8) ;
cout << v1 * v2 . transpose () << endl ;
cout << v1 . dot ( v2 ) << endl << endl ;
cout << v1 . normalized () << endl << endl ;
cout << v1 . cross ( v2 ) << endl ;
cout << v1 . array () * v2 . array () << endl << endl ;
cout << v1 . array () . sin () << endl ;