Eigen Quick Reference
一个 Eigen 的参考手册,包含 Python(Numpy) 与 Eigen 的对应用法,以及一些练习题。持续更新中。
Eigen array, matrix and vector types
在 Eigen 中,Matrix 用来表示数学意义上的矩阵和向量,Array 用来表示 1D 和 2D 的数组,你可以这样定义它们:
typedef Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime, Options> MyMatrixType;
typedef Array<Scalar, RowsAtCompileTime, ColsAtCompileTime, Options> MyArrayType;
- Scalar 表示系数的类型(例如float, double, boll, int 等等)。
- RowsAtCompileTime 和 ColsAtCompileTime 表示矩阵行数和列数(必须在编译时期给定),或者使用 Dynamic 表示其行数或者列数在运行时期给定。
- Options 可以是 ColMajor 或者 RowMajor,它们表示存储数据的顺序,默认是 ColMajor。( 这里 有存储顺序的更多介绍)
你可以随意的组合上面的参数来创建 Matrix,例如
Matrix<double, 6, Dynamic> // 动态列数(堆分配)
Matrix<double, Dynamic, 2> // 动态行数(堆分配)
Matrix<double, Dynamic, Dynamic, RowMajor> // 动态大小,RowMajor(堆大小)
Matrix<double, 13, 3> // 固定大小(通常是栈大小)
你还可以使用更加简易形式来表示一些常用的 Matrix 或者 Array,例如
Matrices | Arrays |
---|---|
Matrix<float, Dynamic, Dynamic> <=> MatrixXf |
Array<float,Dynamic,Dynamic> <=> ArrayXXf |
Matrix<double, Dynamic, 1> <=> VectorXd |
Array<double,Dynamic,1> <=> ArrayXd |
Matrix<int, 1, Dynamic> <=> RowVectorXi |
Array<int,1,Dynamic> <=> RowArrayXi |
Matrix<float, 3, 3> <=> Matrix3f |
Array<float,3,3> <=> Array33f |
Matrix<float, 4, 1> <=> Vector4f |
Array<float,4,1> <=> Array4f |
Which should I choose: matrix or array
如果你也有类似的困惑,很大几率是因为你比较熟悉 Python(NumPy) 或者 MATLAB。
在 MATLAB 中所有变量都是多维数组,矩阵是指通常用来进行线性代数运算的二维数组(它还是个数组),MATALB 具有两种运算:数组运算和矩阵运算。所以 MATLAB 并不区分数组类型或者矩阵类型,它只区分数组操作或者矩阵操作。
在 Python(NumPy)中,你可以用 np.matrix
创建矩阵,np.array
创建数组,但是官方推荐用 np.array
,原因是:
Use arrays.
- They are the standard vector/matrix/tensor type of numpy. Many numpy functions return arrays, not matrices.
- There is a clear distinction between element-wise operations and linear algebra operations.
- You can have standard vectors or row/column vectors if you like.
Until Python 3.5 the only disadvantage of using the array type was that you had to use dot instead of * to multiply (reduce) two tensors (scalar product, matrix vector multiplication etc.). Since Python 3.5 you can use the matrix multiplication @ operator.
Given the above, we intend to deprecate matrix eventually.
由于 NumPy 的便利性,我们通常用 np.array
也能够完成线性代数相关的任务,进一步导致 np.matrix
存在感很弱。
但在 Eigen 中 matrix 与 array 是有明确区别的,总的来说,Eigen 中的 matrix 与线性代数息息相关,它设计的初衷就是为了解决线性代数问题,例如解线性方程组、求矩阵特征值、矩阵的秩、QR分解等等。而 array 则负责系数运算,例如所有系数加上一个常数或者两个 array 系数相乘。
因此,如果你需要线性代数的操作时,请使用 matrix;如果你需要系数操作时,请使用 array。但有时候事情不会那么简单,你可能需要同时使用 matrix 和 array,这种情况下,你需要对 matrix 和 array 进行相互转换。
一个 matrix 通过 .array()
来得到一个 array 表达式;相似的,一个 array 通过 .matrix()
来得到一个 matrix 表达式。.array()
和 .matrix()
不会有任何运行时开销,它们是在编译期完成的。
Matrix 和 Array 之间可以相互转换:
Array44f a1, a1;
Matrix4f m1, m2;
m1 = a1 * a2; // 系数相乘,隐式地从 Array 转到 Matrix
a1 = m1 * m2; // 矩阵相乘,隐式地从 Matrix 转到 Array
a2 = a1 + m1.array(); // Array 和 Matrix 混合使用是不被允许的,需要显式地转换
m2 = a1.matrix() + m1;
ArrayWrapper<Matrix4f> m1a(m1); // m1a 是 m1 的别名,它们共享同样的数据
MatrixWrapper<Array44f> a1m(a1);// a1m 是 a1 的别名,它们共享同样的数据
Initialization
int rows = 5;
int cols = 3;
int size = 3;
// fixed-size array
{
Array33f a1 = Array33f::Zero(); // np.zeros((3,3))
Array33f a2 = Array33f::Random(); // np.random.rand(3,3)
Array33f a3 = Array33f::Ones(); // np.ones((3,3))
Array3f a4 = Array3f::LinSpaced(3, 0, 2); // np.linspace(0,2,3)
Array33f a5 = Array33f::Constant(1.0); // np.full((3,3), 1.0)
}
// one-dimensional dynamic-size
{
ArrayXf a1 = ArrayXf::Zero(cols); // np.zeros(cols)
ArrayXf a2 = ArrayXf::Random(cols); // np.random.rand(cols)
ArrayXf a3 = ArrayXf::Ones(cols); // np.ones(cols)
ArrayXf a4 = ArrayXf::LinSpaced(size, 0, 2); // np.linspace(0,2,size)
ArrayXf a5 = ArrayXf::Constant(cols, 1.0); // np.full(cols, 1.0)
}
// two-dimensional dynamic-size
{
ArrayXXf a1 = ArrayXXf::Zero(rows,cols); // np.zeros((rows, cols)))
ArrayXXf a2 = ArrayXXf::Random(rows,cols); // np.random.rand(rows, cols)
ArrayXXf a3 = ArrayXXf::Ones(rows, cols); // np.ones((rows, cols))
ArrayXXf a4 = ArrayXXf::Constant(rows, cols, 1.0); // np.full((rows, cols), 1.0)
MatrixXf m1 = MatrixXf::Identity(rows, cols); // np.eye(rows, cols)
MatrixXf m2 = Vector3f{1,2,3}.asDiagonal(); // np.diag((1,2,3))
}
Repeating
ArrayXXf a(2,2);
a << 1,2,
3,4;
a.replicate(2, 1); // np.tile(a, (2,1)), repeat array by row
a.replicate(1, 2); // np.tile(a, (1,2)), repeat array by column
a.replicate(2, 3); // np.tile(a, (2,3))
Miss those elements out
ArrayXf a = ArrayXf::Random(10);
// NumPy
a.head(2); // a[:2], the first two element
a.tail(a.size() - 1); // a[1:], miss the first element
a.segment(1, 2); // a[1:3], middle element
a.tail(1); // a[-1], last element
a.tail(2); // a[-2:], last two element
ArrayXXf A = ArrayXXf::Random(10,10);
A.leftCols(2); // a[:, :2], the first two columns
A.topRows(2); // a[:2, :], the first two rows
A.bottomRows(A.rows() - 1); // a[1:, :], miss the first row
A.rightCols(A.cols() - 1); // a[:, 1:], miss the first column
A.middleCols(1, 2); // a[:, 1:3], middle columns
A.middleRows(1, 2); // a[1:3, :], middle rows
A.rightCols(1); // a[:, -1], last column
A.bottomRows(1); // a[-1, :], last row
A.rightCols(2); // a[:, -2:], last two column
A.bottomRows(2); // a[-2:, :], last two row
Slicing
ArrayXf a = ArrayXf::LinSpaced(20, 0, 19);
Map<ArrayXf, 0, InnerStride<2>> v1(a.data(), a.size()/2); // a[::2]
Map<ArrayXf, 0, InnerStride<2>> v2(a.middleRows(1, 6).data(), 3);// a[1:7:2]
ArrayXXf A = ArrayXXf::Random(8,10);// Column-major storage
Map<ArrayXXf, 0, OuterStride<>> A1(A.data(), A.rows(), (A.cols() + 1)/2, OuterStride<>(A.outerStride()*2)); // A[:,::2]
typedef Array<float, Dynamic, Dynamic, RowMajor> RowMajorArrayXXf;
RowMajorArrayXXf A2(A);
Map<RowMajorArrayXXf, 0, OuterStride<>> A3(A2.data(), (A2.rows() + 1)/2, A2.cols(), OuterStride<>(A2.outerStride()*2)); // A[::2, :]
Indexing and accessing elements
更多关于索引和元素访问的细节请参看 block operations
ArrayXXf a = ArrayXXf::Random(3,4);
// NumPy
a(1,2); // a[1,2], element 1,2
a.row(0); // a[0,], first row
a.col(0); // a[:,0], first column
a.middleRows(1, 2); // a[1:3,], middle row
a.middleRows(1, a.rows()-1); // a[1:,], all, except first row
a.bottomRows(a.rows()-1);
a.bottomRows(2); // a[-2:,], last tow rows
Maximum and minimum
ArrayXXf a = ArrayXXf::Random(3,3);
ArrayXXf b = ArrayXXf::Random(3,3);
a.maxCoeff(); // np.max(a), max in array
a.colwise().maxCoeff(); // np.amax(a, axis=0), max in each column
a.rowwise().maxCoeff(); // np.amax(a, axis=1), max in each row
a.max(b); // np.maximum(a,b), pairwise max
Assignment
ArrayXXf a = ArrayXXf::Random(3,3);
// NumPy
a.col(0) = 99; // a[:,0] = 99;
a.col(0) = Array3f{99,98,97}; // a[:,0] = np.array([99, 98, 97])
(a > 90).select(a, 90); // (a>90).choose(a, 90)
Concatenation
// Concatenation(vectors)
Array3f a{1,1,1};
Array3f b{2,2,2};
ArrayXf c( a.size() + b.size() );
c << a, b; // np.concatenate((a,b))
// Concatenation(matrix)
int rows = 3;
int cols = 3;
ArrayXXf A = ArrayXXf::Constant(rows, cols, 1.0f);
ArrayXXf B = ArrayXXf::Constant(rows, cols, 2.0f);
ArrayXXf BindRows(A.rows() + B.rows(), cols);
BindRows << A,B; // np.concatenate((A,B), axis=0)
// or np.vstack((a,b))
ArrayXXf BindCols(rows, A.cols() + B.cols());
BindCols << A,B; // np.concatenate((A,B), axis=1)
// or np.hstack((a,b))
ArrayXf C(A.size() + B.size()); // np.concatenate((a,b), axis=None)
C << Map<ArrayXf>(A.data(), A.size()), // concatenate matrices into a 1d array
Map<ArrayXf>(B.data(), B.size());
Reshape and flatten matrices
ArrayXXf a = ArrayXXf::Random(3,4); // Column-major storage
// NumPy
Map<ArrayXXf> b(a.data(), 2, 6); // np.reshape(a, (2,6))
Map<ArrayXf> v(a.data(), a.size()); // a.flatten("F"), flatten in column-major
Coefficient-wise math functions
下面列举一些常用的 coefficient-wise 数学运算函数,更多详细的内容请参看 Catalog of coefficient-wise math functions
Basic operatoins
Python | Eigen | Description |
---|---|---|
abs(a) | a.abs(); Eigen::abs(a); m.cwiseAbs() | absolute value () |
reciprocal(a) | a.inverse(); Eigen::inverse(a); m.cwiseInverse() | inverse vaule() |
a.conj() | a.conjugate(); Eigen::conj(a); m.conjugate(); | complex conjugate() |
Exponential and logarithm
Python | Eigen | Description |
---|---|---|
math.log(a) | a.log(); log(a) | logarithm, base (natural) |
math.log10(a) | a.log10(); log10(a) | logarithm, base 10 |
math.exp(a) | a.exp(); exp(a) | exponential function |
math.log1p(a) | a.log1p(); log1p(a) | natural (base ) logarithm of 1 plus the given number ( ) |
Round off
Python | Eigen | Description |
---|---|---|
around(a) or math.round(a) | a.round() | Round |
ceil(a) | a.ceil() | Round up |
floor(a) | a.floor() | Round down |
Power functions
Python | Eigen | Description |
---|---|---|
power(a,b) | a.pow(b) | power, |
math.sqrt(a) | a.sqrt(); Eigen::sqrt(a); m.cwiseSqrt() | square root () |
square(a) | a.square(); Eigen::square(a) | square power() |
power(a,3) | a.cube(); Eigen::cube(a) | cubic power() |
abs(a).square() | a.abs2(); Eigen::abs2(a);m.cwiseAbs2() | squared absolute value() |
Trigonometric functions
Python | Eigen | Description |
---|---|---|
sin(a) | a.sin(); Eigen::sin(a) | computes sine |
cos(a) | a.cos(); Eigen::cos(a) | computes cosine |
tan(a) | a.tan(); Eigen::tan(a) | computes tangent |
arcsin(a) | a.asin(); Eigen::asin(a) | computes arc sine() |
arccos(a) | a.acos(); Eigen::acos(a) | computes arc cosine() |
arctan(a) | a.atan(); Eigen::atan(a) | computes arc tangent() |
Eigen exercise
/*
* Eigen exercise
*
* This is quick reference of Eigen.
*
* We use Eigen to implement 100 Numpy(some of them) (https://github.com/rougier/numpy-100)
*
* It is highly recommended to read Eigen document before starting if you never read it
*
*/
#include <Eigen/Core>
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
#include <map>
#include <unsupported/Eigen/CXX11/Tensor>
#include <complex>
#include <cmath>
using namespace std;
using namespace Eigen;
void exercise_2()
{
// 2. Print the eigen version
cout << "Eigen version " << EIGEN_MAJOR_VERSION << "."
<< EIGEN_MINOR_VERSION << endl;
}
void exercise_3()
{
// 3 Create a null vector of size 10 (★☆☆)
VectorXf Z = VectorXf::Zero(10);
cout << Z << endl;
}
void exercise_4()
{
// 4. How to find the memory size of any array (★☆☆)
MatrixXf Z = MatrixXf::Zero(10, 10);
cout << Z.size() * sizeof(MatrixXf::Scalar) << endl;
}
void exercise_6()
{
// 6. Create a null vector of size 10 but the fifth value which is 1 (★☆☆)
VectorXf Z = VectorXf::Zero(10);
Z(4) = 1;
cout << Z << endl;
}
void exercise_7()
{
// 7. Create a vector with values ranging from 10 to 49 (★☆☆)
const int start = 10;
const int end = 49;
const int size = end - start + 1;
VectorXf Z = VectorXf::LinSpaced(size, start, end);
cout << Z << endl;
}
void exercise_8()
{
// 8. Reverse a vector (first element becomes last) (★☆☆)
VectorXf Z = VectorXf::LinSpaced(10, 1, 10);
Z = Z.reverse().eval();
cout << Z << endl;
// Z = Z.reverse() is aliasing
// you can use .eval() or inplace to solve this:
// Z = Z.reverse().eval()
// Z.reverseInPlace()
}
void exercise_9()
{
//9. Create a 3x3 matrix with values ranging from 0 to 8 (★☆☆)
// Eigen does not expose convenient methods to take slices or to reshape a matrix yet.
// Nonetheless, such features can easily be emulated using the Map class.
VectorXf Z1 = VectorXf::LinSpaced(9, 1, 9);
Map<MatrixXf> Z2(Z1.data(), 3, 3);
cout << Z2 << endl;
}
void exercise_10()
{
// 10. Find indices of non-zero elements from [1,2,0,0,4,0] (★☆☆)
VectorXf Z(6);
Z << 1,2,0,0,4,0;
std::vector<Index> nz;
for(Index i = 0; i < Z.size(); ++i)
{
if(Z(i))
{
nz.push_back(i);
}
}
Map<Matrix<Index , 1, Dynamic>> nzz(nz.data(), nz.size());
cout << nzz;
}
void exercise_11()
{
// 11. Create a 3x3 identity matrix (★☆☆)
MatrixXf Z = MatrixXf::Identity(3,3);
cout << Z << endl;
}
void exercise_12()
{
// 12. Create a 3x3x3 array with random values (★☆☆)
// NOTE: Tensor is unsupported module in 3.3.7
Tensor<float,3> T(3,3,3);
T.setRandom();
cout << T << endl;
// 12.1 Create a 3x3 array with random values (★☆☆)
MatrixXf Z = MatrixXf::Random(3,3);
cout << Z << endl;
}
void exercise_13()
{
// 13. Create a 10x10 array with random values and find the minimum and maximum values (★☆☆)
MatrixXf Z = MatrixXf::Random(10, 10);
cout << Z.maxCoeff() << "," << Z.minCoeff() << endl;
}
void exercise_14()
{
// 14. Create a random vector of size 30 and find the mean value (★☆☆)
VectorXf Z = VectorXf::Random(30);
cout << Z.mean() << endl;
}
void exercise_15()
{
// 15. Create a 2d array with 1 on the border and 0 inside (★☆☆)
MatrixXf Z = MatrixXf::Zero(5, 5);
VectorXf padding = VectorXf::Constant(5, -1);
Z.topRows<1>() = padding;
Z.bottomRows<1>() = padding;
Z.leftCols<1>() = padding;
Z.rightCols<1>() = padding;
cout << Z << endl;
}
void exercise_16()
{
// 16. How to add a border (filled with 0's) around an existing array? (★☆☆)
MatrixXf Z = MatrixXf::Ones(5, 5);
Z.conservativeResize(6,6);
VectorXf padding = VectorXf::Zero(6);
Z.topRows<1>() = padding;
Z.bottomRows<1>() = padding;
Z.leftCols<1>() = padding;
Z.rightCols<1>() = padding;
cout << Z << endl;
}
void exercise_18()
{
// 18. Create a 5x5 matrix with values 1,2,3,4 just below the diagonal (★☆☆)
// Is difficult to implement in Eigen, but create a diagonal is easy
VectorXf V(4);
V << 1, 2, 3, 4;
MatrixXf Z = V.asDiagonal();
cout << Z << endl;
}
void exercise_21()
{
// 21. Create a checkerboard 8x8 matrix using the tile function (★☆☆)
MatrixXf Z(2,2);
Z << 0,1,
1,0;
cout << Z.replicate(4, 4) << endl;
}
void exercise_22()
{
// 22. Normalize a 5x5 random matrix (★☆☆)
MatrixXf Z = MatrixXf::Random(5,5);
float mean = Z.mean();
float std = std::sqrt( (Z.array() - mean).square().sum() / (Z.size() - 1) );
Z = (Z.array() - mean) / (std);
cout << Z << endl;
}
void exercise_24()
{
// 24. Multiply a 5x3 matrix by a 3x2 matrix (real matrix product) (★☆☆)
MatrixXf A = MatrixXf::Ones(5,3);
MatrixXf B = MatrixXf::Ones(3,2);
MatrixXf Z = A * B;
cout << Z << endl;
}
void exercise_25()
{
// 25. Given a 1D array, negate all elements which are between 3 and 8, in place. (★☆☆)
VectorXf Z = VectorXf::LinSpaced(11, 0, 10);
Matrix<float, Dynamic, 1> B = (3 < Z.array() && Z.array() <= 8).cast<float>() * -1.0;
Matrix<float, Dynamic, 1> C = B.array() + 1.0;
cout << Z.array() * B.array() + Z.array() * C.array() << endl;
}
void exercise_30()
{
// 30. How to find common values between two arrays? (★☆☆)
std::mt19937 gen(0);
std::uniform_int_distribution<int> dis(0, 10);
// generate random int numbers in range [0, 10]
auto func = [&](int x){return dis(gen);};
VectorXi A = VectorXd::Zero(10).unaryExpr(func);
VectorXi B = VectorXd::Zero(10).unaryExpr(func);
std::set<int> commom_values_set;
auto find_common_values = [&](int x){
if( (B.array() == x).any() )
{
commom_values_set.insert(x);
}
return x;
};
A = A.unaryExpr(find_common_values);
for(const auto& v : commom_values_set)
{
cout << v << " ";
}
}
void exercise_39()
{
// 39. Create a vector of size 10 with values ranging from 0 to 1, both excluded (★★☆)¶
VectorXf Z = VectorXf::LinSpaced(12, 0, 1);
Z = Z.segment(1, 10);
cout << Z << endl;
}
void exercise_40()
{
// 40. Create a random vector of size 10 and sort it (★★☆)
VectorXf Z = VectorXf::Random(10);
sort(Z.data(), Z.data()+Z.size(), [](float x, float y){return x < y;});
cout << Z << endl;
}
void exercise_40_1()
{
// 40_1. Create a random matrix of size 10x10 and sort it row by row (★★☆)
MatrixXf Z = MatrixXf::Random(10, 10);
auto sort_func = [](float x, float y){return x<y;};
std::vector<MatrixXf::Scalar> data(Z.cols());
for(int i = 0; i < Z.rows(); ++i)
{
// copy row to data array
for(int j = 0; j < Z.cols(); ++j)
{
data[j] = Z(i, j);
}
// sort data array
sort(data.begin(), data.end(), sort_func);
// copy back to row
for(int j = 0; j < Z.cols(); ++j)
{
Z(i, j) = data[j];
}
}
cout << Z << endl;
}
void exercise_40_2()
{
// 40_2. Create a random matrix of size 10x10 and sort it col by col (★★☆)
MatrixXf Z = MatrixXf::Random(10, 10);
auto sort_func = [](float x, float y){return x<y;};
std::vector<MatrixXf::Scalar> data(Z.rows());
for(int i = 0; i < Z.cols(); ++i)
{
// copy row to data array
for(int j = 0; j < Z.rows(); ++j)
{
data[j] = Z(j, i);
}
// sort data array
sort(data.begin(), data.end(), sort_func);
// copy back to row
for(int j = 0; j < Z.rows(); ++j)
{
Z(j, i) = data[j];
}
}
cout << Z << endl;
}
void exercise_42()
{
// 42. Consider two random array A and B, check if they are equal (★★☆)
MatrixXf A = MatrixXf::Random(5,5);
MatrixXf B = MatrixXf::Random(5,5);
bool equal = (A.array() == B.array()).all();
cout << equal << endl;
}
void exercise_44()
{
// 44. Consider a random 10x2 matrix representing cartesian coordinates, convert them to polar coordinates (★★☆)
MatrixXf Z = MatrixXf::Random(10, 2);
VectorXf X = Z.col(0);
VectorXf Y = Z.col(1);
VectorXf R = (X.array().square() + Y.array().square()).sqrt();
VectorXf T = (Y.array()/X.array()).atan();
cout << "R:\n" << R << endl;
cout << "T:\n" << T << endl;
}
void exercise_45()
{
// 45. Create random vector of size 10 and replace the maximum value by 0 (★★☆)
VectorXf Z = VectorXf::Random(10);
VectorXf::Index max_index;
Z.maxCoeff(&max_index);
Z(max_index) = 0.0;
cout << Z << endl;
}
void exercise_47()
{
// 47. Given two arrays, X and Y, construct the Cauchy matrix C (Cij =1/(xi - yj))
VectorXf X = VectorXf::LinSpaced(8, 0, 7);
VectorXf Y = X.array() + 0.5;
MatrixXf C(X.size(), Y.size());
for(int i = 0; i < C.cols(); ++i)
{
C.col(i) = 1.0/(X.array() - Y(i));
}
cout << C << endl;
}
void exercise_50()
{
// 50. How to find the closest value (to a given scalar) in a vector? (★★☆)
VectorXf Z = VectorXf::LinSpaced(100, 0, 99);
float v = 10;
VectorXf::Index index;
(Z.array() - v).abs().minCoeff(&index);
cout << index << endl;
}
void exercise_52()
{
// 52. Consider a random vector with shape (10,2) representing coordinates, find point by point distances (★★☆)
MatrixXf Z = MatrixXf::Random(10, 2);
Matrix<float, Dynamic, 1> X = Z.col(0);
Matrix<float, Dynamic, 1> Y = Z.col(1);
MatrixXf XX = X.rowwise().replicate(10);
MatrixXf YY = Y.rowwise().replicate(10);
MatrixXf D = (XX - XX.transpose()).array().square() + (YY - YY.transpose()).array().square();
cout << D.cwiseSqrt() << endl; // D.cwiseSqrt() = D.array().sqrt()
}
void exercise_56()
{
// 56. Generate a generic 2D Gaussian-like array (★★☆)
// Matrix<float,Dynamic,1> X =
VectorXf V = VectorXf::LinSpaced(10, -1, 1);
MatrixXf Y = V.rowwise().replicate(10);
MatrixXf X = Y.transpose();
MatrixXf G = (X.array().square() + Y.array().square()).cwiseSqrt();
float sigma = 1.0;
float mu = 0.0;
MatrixXf result = ( -(G.array() - mu).square() / (2.0 * sigma*sigma) ).exp();
cout << result << endl;
}
void exercise_58()
{
// 58. Subtract the mean of each row of a matrix (★★☆)¶
MatrixXf Z = MatrixXf::Random(5, 10);
VectorXf mean = Z.rowwise().mean();
cout << Z.colwise() - mean << endl;
}
void exercise_59()
{
// 59. How to sort an array by the nth column? (★★☆)
MatrixXf Z = MatrixXf::Random(3,3);
cout << Z << endl << endl;
int n = 1; // first column
auto compare_nth = [&n](const VectorXf& lhs, const VectorXf& rhs){
return lhs(n) < rhs(n);
};
std::vector<VectorXf> vec;
for(int i = 0; i < Z.rows(); ++i)
{
vec.emplace_back(Z.row(i));
}
std::sort(vec.begin(), vec.end(), compare_nth);
for(int i = 0; i < Z.rows(); ++i)
{
Z.row(i) = vec[i];
}
cout << Z << endl;
}
void exercise_60()
{
// 60. How to tell if a given 2D array has null columns? (★★☆)
MatrixXf Z = MatrixXf::Random(5,5);
Z(0,0) = sqrt(-1); // genenrate a nan
cout << Eigen::isnan(Z.array()).any() << endl;
cout << Eigen::isnan(Z.array()).select(0, Z) << endl;
}
void exercise_61()
{
// 61. Find the nearest value from a given value in an array (★★☆)
VectorXf Z = VectorXf::Random(10);
float z = 0.5;
VectorXf::Index min_index;
(Z.array() - z).abs().minCoeff(&min_index);
cout << Z(min_index) << endl;
}
void exercise_64()
{
// 64. Consider a given vector, how to add 1 to each element indexed by a second vector (be careful with repeated indices)? (★★★)
VectorXf Z = VectorXf::Ones(10);
VectorXi I(20);
I << 7, 4, 2, 6, 4, 8, 6, 3, 0, 8, 1, 0, 5, 1, 9, 7, 5, 1, 8, 7;
std::map<int, int> bins;
for(int i = 0; i < I.size(); ++i)
{
const int key = I(i);
if(bins.find(key) != bins.end())
{
++bins[key];
} else
{
bins[key] = 1;
}
}
for(int i = 0; i < Z.size(); ++i)
{
Z(i) += bins[i];
}
cout << Z << endl;
}
来源:CSDN
作者:芥末的无奈
链接:https://blog.csdn.net/weiwei9363/article/details/104307649