R语言学习RcppEigen进行矩阵运算

目录

  • 创建cpp文件
    • 代码示例
  • 其他矩阵操作
    • 命名
    • 基础用法
    • 定义矩阵
    • 对矩阵的一些基础操作1
    • 基础操作2
    • 矩阵基础运算1
    • 矩阵基础运算2
    • 求最小最大值、迹等
    • 点乘等
    • 特征值与特征向量
    • 形式转换
    • 矩阵初始化0
    • Map等操作
    • 求解Ax = b
前面我们介绍了一些基本的Rcpp的用法:让你的R代码更快——Rcpp入门,但用基础的Rcpp来进行矩阵运算还是非常麻烦,没有现成的函数来让我们使用。
这时我们就想到:是否可以调用别的库来解决矩阵运算的一些问题呢?这就需要我们的RcppEigen包,也就是C++中的Eigen库。
这些矩阵的运算在进行模拟时会时常遇到,所以可以说是非常重要的一项技能,下面我们就给予一个现有的对矩阵处理的代码来说明其用法。

创建cpp文件 其创建方式可以参考上篇博客:让你的R代码更快——Rcpp入门

代码示例
然后我们定义一个
R语言学习RcppEigen进行矩阵运算
文章图片

来做矩阵乘法并求其迹(trace)的函数。
// [[Rcpp::depends(RcppEigen)]]#include using namespace Eigen; using namespace std; //[[Rcpp::export]]double myfun (MatrixXd X, MatrixXd Y) {double Z; Z = (X.adjoint() * Y).trace(); cout << Z << endl; return Z; }

前三行表示载入Eigen
// [[Rcpp::depends(RcppEigen)]]#include using namespace Eigen;

里面的转置函数adjoint(),求迹函数trace(),都需要用到这个库,如果不使用命名空间Eigen后面库里面就要这样用Eigen::adjoint()Eigen::trace()
后面我们使用using namespace std; 则是因为cout需要用到,这个可以在运行函数的时候展现我们的中间变量,也是一个比较有用的操作,当然如果不需要的话,就可以不用命名变量空间:std
【R语言学习RcppEigen进行矩阵运算】下面就是我们的函数:
//[[Rcpp::export]]double myfun (MatrixXd X, MatrixXd Y) {double Z; Z = (X.adjoint() * Y).trace(); cout << Z << endl; return Z; }

//[[Rcpp::export]]为我们需要导出到R中的时候需要添加,double型的矩阵在Eigen中命名为MatrixXd,整型矩阵为MatrixXi;类似,对应的向量命名方式为:VectorXdVectorXi
里面的内容就是我们按照公式敲的函数。
下面我们介绍一些Eigen库中的其它一些矩阵操作。

其他矩阵操作 这部分原文:A simple quickref for Eigen

命名
Matrix A; // Fixed rows and cols. Same as Matrix3d.Matrix B; // Fixed rows, dynamic cols.Matrix C; // Full dynamic. Same as MatrixXd.Matrix E; // Row major; default is column-major.Matrix3f P, Q, R; // 3x3 float matrix.Vector3f x, y, z; // 3x1 float matrix.RowVector3f a, b, c; // 1x3 float matrix.VectorXd v; // Dynamic column vector of doublesdouble s;


基础用法
// Basic usage// Eigen// Matlab// commentsx.size()// length(x)// vector sizeC.rows()// size(C,1)// number of rowsC.cols()// size(C,2)// number of columnsx(i)// x(i+1)// Matlab is 1-basedC(i,j)// C(i+1,j+1)//A.resize(4, 4); // Runtime error if assertions are on.B.resize(4, 9); // Runtime error if assertions are on.A.resize(3, 3); // Ok; size didn't change.B.resize(3, 9); // Ok; only dynamic cols changed.A << 1, 2, 3,// Initialize A. The elements can also be4, 5, 6,// matrices, which are stacked along cols7, 8, 9; // and then the rows are stacked.B << A, A, A; // B is three horizontally stacked A's.A.fill(10); // Fill A with all 10's.


定义矩阵
// Eigen// MatlabMatrixXd::Identity(rows,cols)// eye(rows,cols)C.setIdentity(rows,cols)// C = eye(rows,cols)MatrixXd::Zero(rows,cols)// zeros(rows,cols)C.setZero(rows,cols)// C = zeros(rows,cols)MatrixXd::Ones(rows,cols)// ones(rows,cols)C.setOnes(rows,cols)// C = ones(rows,cols)MatrixXd::Random(rows,cols)// rand(rows,cols)*2-1// MatrixXd::Random returns uniform random numbers in (-1, 1).C.setRandom(rows,cols)// C = rand(rows,cols)*2-1VectorXd::LinSpaced(size,low,high)// linspace(low,high,size)'v.setLinSpaced(size,low,high)// v = linspace(low,high,size)'VectorXi::LinSpaced(((hi-low)/step)+1,// low:step:hilow,low+step*(size-1))//


对矩阵的一些基础操作1
// Matrix slicing and blocks. All expressions listed here are read/write.// Templated size versions are faster. Note that Matlab is 1-based (a size N// vector is x(1)...x(N)).// Eigen// Matlabx.head(n)// x(1:n)x.head()// x(1:n)x.tail(n)// x(end - n + 1: end)x.tail()// x(end - n + 1: end)x.segment(i, n)// x(i+1 : i+n)x.segment(i)// x(i+1 : i+n)P.block(i, j, rows, cols)// P(i+1 : i+rows, j+1 : j+cols)P.block(i, j)// P(i+1 : i+rows, j+1 : j+cols)P.row(i)// P(i+1, :)P.col(j)// P(:, j+1)P.leftCols()// P(:, 1:cols)P.leftCols(cols)// P(:, 1:cols)P.middleCols(j)// P(:, j+1:j+cols)P.middleCols(j, cols)// P(:, j+1:j+cols)P.rightCols()// P(:, end-cols+1:end)P.rightCols(cols)// P(:, end-cols+1:end)P.topRows()// P(1:rows, :)P.topRows(rows)// P(1:rows, :)P.middleRows(i)// P(i+1:i+rows, :)P.middleRows(i, rows)// P(i+1:i+rows, :)P.bottomRows()// P(end-rows+1:end, :)P.bottomRows(rows)// P(end-rows+1:end, :)P.topLeftCorner(rows, cols)// P(1:rows, 1:cols)P.topRightCorner(rows, cols)// P(1:rows, end-cols+1:end)P.bottomLeftCorner(rows, cols)// P(end-rows+1:end, 1:cols)P.bottomRightCorner(rows, cols)// P(end-rows+1:end, end-cols+1:end)P.topLeftCorner()// P(1:rows, 1:cols)P.topRightCorner()// P(1:rows, end-cols+1:end)P.bottomLeftCorner()// P(end-rows+1:end, 1:cols)P.bottomRightCorner()// P(end-rows+1:end, end-cols+1:end)


基础操作2
// Of particular note is Eigen's swap function which is highly optimized.// Eigen// MatlabR.row(i) = P.col(j); // R(i, :) = P(:, j)R.col(j1).swap(mat1.col(j2)); // R(:, [j1 j2]) = R(:, [j2, j1])

// Views, transpose, etc; // Eigen// MatlabR.adjoint()// R'R.transpose()// R.' or conj(R')// Read-writeR.diagonal()// diag(R)// Read-writex.asDiagonal()// diag(x)R.transpose().colwise().reverse()// rot90(R)// Read-writeR.rowwise().reverse()// fliplr(R)R.colwise().reverse()// flipud(R)R.replicate(i,j)// repmat(P,i,j)


矩阵基础运算1
// All the same as Matlab, but matlab doesn't have *= style operators.// Matrix-vector.Matrix-matrix.Matrix-scalar.y= M*x; R= P*Q; R= P*s; a= b*M; R= P - Q; R= s*P; a *= M; R= P + Q; R= P/s; R *= Q; R= s*P; R += Q; R *= s; R -= Q; R /= s;


矩阵基础运算2
// Vectorized operations on each element independently// Eigen// MatlabR = P.cwiseProduct(Q); // R = P .* QR = P.array() * s.array(); // R = P .* sR = P.cwiseQuotient(Q); // R = P ./ QR = P.array() / Q.array(); // R = P ./ QR = P.array() + s.array(); // R = P + sR = P.array() - s.array(); // R = P - sR.array() += s; // R = R + sR.array() -= s; // R = R - sR.array() < Q.array(); // R < QR.array() <= Q.array(); // R <= QR.cwiseInverse(); // 1 ./ RR.array().inverse(); // 1 ./ RR.array().sin()// sin(R)R.array().cos()// cos(R)R.array().pow(s)// R .^ sR.array().square()// R .^ 2R.array().cube()// R .^ 3R.cwiseSqrt()// sqrt(R)R.array().sqrt()// sqrt(R)R.array().exp()// exp(R)R.array().log()// log(R)R.cwiseMax(P)// max(R, P)R.array().max(P.array())// max(R, P)R.cwiseMin(P)// min(R, P)R.array().min(P.array())// min(R, P)R.cwiseAbs()// abs(R)R.array().abs()// abs(R)R.cwiseAbs2()// abs(R.^2)R.array().abs2()// abs(R.^2)(R.array() < s).select(P,Q ); // (R < s ? P : Q)R = (Q.array()==0).select(P,R) // R(Q==0) = P(Q==0)R = P.unaryExpr(ptr_fun(func)) // R = arrayfun(func, P)// with: scalar func(const scalar &x);


求最小最大值、迹等
// Reductions.int r, c; // Eigen// MatlabR.minCoeff()// min(R(:))R.maxCoeff()// max(R(:))s = R.minCoeff(&r, &c)// [s, i] = min(R(:)); [r, c] = ind2sub(size(R), i); s = R.maxCoeff(&r, &c)// [s, i] = max(R(:)); [r, c] = ind2sub(size(R), i); R.sum()// sum(R(:))R.colwise().sum()// sum(R)R.rowwise().sum()// sum(R, 2) or sum(R')'R.prod()// prod(R(:))R.colwise().prod()// prod(R)R.rowwise().prod()// prod(R, 2) or prod(R')'R.trace()// trace(R)R.all()// all(R(:))R.colwise().all()// all(R)R.rowwise().all()// all(R, 2)R.any()// any(R(:))R.colwise().any()// any(R)R.rowwise().any()// any(R, 2)


点乘等
// Dot products, norms, etc.// Eigen// Matlabx.norm()// norm(x).Note that norm(R) doesn't work in Eigen.x.squaredNorm()// dot(x, x)Note the equivalence is not true for complexx.dot(y)// dot(x, y)x.cross(y)// cross(x, y) Requires #include


特征值与特征向量
// Eigenvalue problems// Eigen// MatlabA.eigenvalues(); // eig(A); EigenSolver eig(A); // [vec val] = eig(A)eig.eigenvalues(); // diag(val)eig.eigenvectors(); // vec// For self-adjoint matrices use SelfAdjointEigenSolver<>


形式转换
Type conversion// Eigen// MatlabA.cast(); // double(A)A.cast(); // single(A)A.cast(); // int32(A)A.real(); // real(A)A.imag(); // imag(A)// if the original type equals destination type, no work is done


矩阵初始化0
// Note that for most operations Eigen requires all operands to have the same type:MatrixXf F = MatrixXf::Zero(3,3); A += F; // illegal in Eigen. In Matlab A = A+F is allowedA += F.cast(); // F converted to double and then added (generally, conversion happens on-the-fly)


Map等操作
// Eigen can map existing memory into Eigen matrices.float array[3]; Vector3f::Map(array).fill(10); // create a temporary Map over array and sets entries to 10int data[4] = {1, 2, 3, 4}; Matrix2i mat2x2(data); // copies data into mat2x2Matrix2i::Map(data) = 2*mat2x2; // overwrite elements of data with 2*mat2x2MatrixXi::Map(data, 2, 2) += mat2x2; // adds mat2x2 to elements of data (alternative syntax if size is not know at compile time)


求解Ax = b
// Solve Ax = b. Result stored in x. Matlab: x = A \ b.x = A.ldlt().solve(b)); // A sym. p.s.d.#include x = A.llt() .solve(b)); // A sym. p.d.#include x = A.lu().solve(b)); // Stable and fast. #include x = A.qr().solve(b)); // No pivoting.#include x = A.svd() .solve(b)); // Stable, slowest. #include // .ldlt() -> .matrixL() and .matrixD()// .llt()-> .matrixL()// .lu()-> .matrixL() and .matrixU()// .qr()-> .matrixQ() and .matrixR()// .svd()-> .matrixU(), .singularValues(), and .matrixV()

以上就是R语言学习RcppEigen进行矩阵运算的详细内容,更多关于RcppEigen矩阵运算的资料请关注脚本之家其它相关文章!

    推荐阅读