函数

时间:2017-11-04 19:29:25

标签: c++ matrix eigen

我试图从内核构建矩阵,这样A(i,j)= f(i,j)其中i,j都是向量(因此我从两个矩阵x,y构建A)每行对应一个点/向量)。我目前的功能与此类似:

Eigen::MatrixXd get_kernel_matrix(const Eigen::MatrixXd& x, const Eigen::MatrixXd& y, double(&kernel)(const Eigen::VectorXd&)) {
    Eigen::MatrixXd res (x.rows(), y.rows());
    for(int i = 0; i < res.rows() ; i++) {
        for(int j = 0; j < res.cols(); j++) {
            res(i, j) = kernel(x.row(i), y.row(j));
            }
        }
    }
    return res;
}

除了对角线的某些逻辑(在我的情况下可能会导致除零)。

有更高效/实际的方法吗?在我的一些测试中,似乎Matlab代码超过了我的C ++ / Eigen实现的速度(我因为矢量化而猜测。)

我查看了相当多的文档(例如unaryExpr函数),但似乎无法找到我正在寻找的内容。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您可以将NullaryExpr与适当的lambda一起使用来删除for循环:

MatrixXd res = MatrixXd::NullaryExpr(x.rows(), y.rows(),
               [&x,&y,&kernel](int i,int j) { return kernel(x.row(i), y.row(j)); });

这是一个重现矩阵产品的工作自包含示例:

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;

double my_kernel(const MatrixXd::ConstRowXpr &x, const MatrixXd::ConstRowXpr &y) {
  return x.dot(y);
}

template<typename Kernel>
MatrixXd apply_kernel(const MatrixXd& x, const MatrixXd& y, Kernel kernel) {
  return MatrixXd::NullaryExpr(x.rows(), y.rows(),
                [&x,&y,&kernel](int i,int j) { return kernel(x.row(i), y.row(j)); });
}

int main()
{
  int n = 10;
  MatrixXd X = MatrixXd::Random(n,n);
  MatrixXd Y = MatrixXd::Random(n,n);
  MatrixXd R = apply_kernel(X,Y,std::ptr_fun(my_kernel));
  std::cout << R << "\n\n";
  std::cout << X*Y.transpose() << "\n\n";
}

如果您不想让apply_kernel成为模板函数,可以使用std :: function来传递内核。