这是我的示例代码:
(请注意包围的部分#if ENABLE_MY_COMPILE_ERROR)
#include <Eigen/Core>
#include <iostream>
#define ENABLE_MY_COMPILE_ERROR 1
void f1(const Eigen::Ref<Eigen::MatrixXd> a,
const Eigen::Ref<Eigen::MatrixXd> b,
Eigen::Ref<Eigen::MatrixXd> c)
{
c = a * b;
}
int main(int argc, const char *argv[])
{
Eigen::Matrix3d M;
Eigen::Vector3d x;
Eigen::Vector3d y;
M.setRandom();
x.setRandom();
std::cout<<"M = \n"<<M<<std::endl;
std::cout<<"x = \n"<<x<<std::endl;
std::cout<<"M * x = \n"<<M * x<<std::endl;
{
y.setZero();
f1(M,x,y);
std::cout<<"y = \n"<<y<<std::endl;
}
{
Eigen::Matrix3d& MRef = M;
y.setZero();
f1(MRef,x,y);
std::cout<<"y = \n"<<y<<std::endl;
}
#if ENABLE_MY_COMPILE_ERROR
{
const Eigen::Matrix3d& MRef …Run Code Online (Sandbox Code Playgroud) 首先,我不确定这是否可行.我想在特征库中检查矩阵是否为零(注意:我必须声明它).我的解决方案是检查所有元素是否为零.我的问题是,在保持矩阵大小不变的情况下,还有另一种方法可以完成这项任务吗?
#include <iostream>
#include <Eigen/Dense>
// true if it is empty, false if not
bool isEmpty(Eigen::MatrixXd& Z)
{
bool check = true;
for (int row(0); row < Z.rows(); ++row)
for (int col(0); col < Z.cols(); ++col){
if ( Z(row,col) != 0 ){
check = false;
break;
}
}
return check;
}
int main()
{
Eigen::MatrixXd Z(3,3);
if ( isEmpty(Z) )
std::cout << Z.size() << std::endl;
else
Z.setZero(0,0); // resize the matrix (not clever way I know)
std::cin.get();
return 0;
}
Run Code Online (Sandbox Code Playgroud) 要将Eigen :: Matrix写入文件我真的很想使用以下内容:
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> Matrix_MxN;
Matrix_MxN J = Matrix_MxN::Zeros(10,10);
std::ofstream("matrix.txt") << J;
Run Code Online (Sandbox Code Playgroud)
但不幸的是,没有定义可以做相反的事情:
std::ifstream("matrix.txt") >> J;
Run Code Online (Sandbox Code Playgroud)
为了避免这个问题,你如何读取/写入Eigen :: Matrix到二进制文件?
我对C++中的Eigen库有疑问.实际上,我想计算稀疏矩阵的逆矩阵.当我在Eigen中使用Dense矩阵时,我可以使用.inverse()运算来计算密集矩阵的逆.但是在稀疏矩阵中,我无法在任何地方找到逆运算.有谁知道计算稀疏矩阵的逆?帮我.
我想了解表达模板在Eigen中是如何工作的.我明白两个动态双向量的总和是由看起来像这样的东西执行的:
CwiseBinaryOp< internal::scalar_sum_op<double>, VectorXd const, VectorXd const > operator+(VectorXd const & lhs, VectorXd const & rhs);
Run Code Online (Sandbox Code Playgroud)
我也理解了如何实现两个向量的差异.
我有两个问题.
1.标量的矢量乘积如何工作?
我注意到
CwiseBinaryOp< internal::scalar_product_op<double>, VectorXd const, VectorXd const >
Run Code Online (Sandbox Code Playgroud)
但我觉得它只是为了在两个向量之间执行分量运算而设计的.这是否意味着标量向量的乘积对应于一元运算符
CwiseUnaryOp< internal::scalar_product_op<double>, VectorXd const, VectorXd const > ?
Run Code Online (Sandbox Code Playgroud)
2.模板表达式可以通过混合操作构建吗?
例如,在表达式中
x = u + (2*v + (v-w))
Run Code Online (Sandbox Code Playgroud)
这些操作是否以这样的嵌套方式执行?
v-w 导致构建E1实例2*v 导致构建E2的实例2*v + (v-w) 导致构建E3实例u + (2*v + (u-w)) 导致构建E4实例x = u + (2*v + (v-w)) 电话 构造函数
VectorXd(E4 const &);
Run Code Online (Sandbox Code Playgroud)
或超载
VectorXd & operator=(E4 const &);
Run Code Online (Sandbox Code Playgroud)
它使用以下别名评估从前面的步骤构建的树:
using …Run Code Online (Sandbox Code Playgroud) 看起来很简单.我本以为某种铸造是可能的,但我似乎找不到任何文件.
虽然我在我的应用程序中找到了避免使用Eigen :: Matrix类的方法,但TensorFlow仅适用于Eigen :: Tensor,而我使用的另一个库只具有直接使用Eigen :: Matrix的功能.如果我可以将Tensor作为矩阵进行投射并使用它,那么代码可读性将是非常壮观的.
编辑:似乎TensorFlow DOES有一个函数来获取Eigen :: Matrix(仍在测试它).也许这会使原始问题变得不那么有趣(也许没有人需要将Tensors转换为Matrices.)但我仍然认为这是一个有效的问题.所以我不会放下我的
编辑2:在一些构建错误之后通过TF文档,似乎tensorflow的Tensor :: matrix()函数只返回一个2d Eigen :: Tensor,所以转换实际上是必要的.
我们正处于将代码库移植到Eigen 3.3 的过程中(相当于所有32字节对齐问题).然而,有一些地方的表现似乎受到严重影响,与预期相反(考虑到对FMA和AVX的额外支持,我期待一些加速......).这些包括特征值分解和矩阵*matrix.transpose()*矢量积.我写了两个最小的工作示例来演示.
所有测试都在最新的Arch Linux系统上运行,使用Intel Core i7-4930K CPU(3.40GHz),并使用g ++版本6.2.1进行编译.
对于Eigen 3.3.0,直接的自伴特征值分解需要两倍于3.2.10.
档案test_eigen_EVD.cpp:
#define EIGEN_DONT_PARALLELIZE
#include <Eigen/Dense>
#include <Eigen/Eigenvalues>
#define SIZE 200
using namespace Eigen;
int main (int argc, char* argv[])
{
MatrixXf mat = MatrixXf::Random(SIZE,SIZE);
SelfAdjointEigenSolver<MatrixXf> eig;
for (int n = 0; n < 1000; ++n)
eig.compute (mat);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
检测结果:
本征3.2.10:
g++ -march=native -O2 -DNDEBUG -isystem eigen-3.2.10 test_eigen_EVD.cpp -o test_eigen_EVD && time ./test_eigen_EVD
real 0m5.136s
user 0m5.133s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)本征3.3.0:
g++ -march=native -O2 …Run Code Online (Sandbox Code Playgroud)我想从 C 型数组映射到列专业特征矩阵。
映射本身使用的是 RowMajor 类型,
所以我试过了
std::vector<double> a(9);
double *p= a.data();
Eigen::MatrixXd M=Eigen::Map<Eigen::Matrix<double, 3, 3, Eigen::RowMajor>>(p)
Run Code Online (Sandbox Code Playgroud)
我得到了我所期望的(M.data() 的顺序),但是,如果在编译时不知道模板中的维度(3),则此方法不起作用......有什么解决方案吗?
看起来将 Eigen 类型与 STL 容器一起使用非常混乱,需要特别注意对齐问题。我的问题是我计划创建具有数十个类的复杂类层次结构,这些类可能包含一个或多个特征类型作为成员变量。从文档看来,只要您在成员变量中包含 Eigen 类型,您的类就会“感染”与 Eigen 类型相同的问题。这意味着我必须格外小心地使用 STL 容器,不仅用于 Eigen 类型,而且还用于我所有的几十个类。
让我担心的更糟糕的部分是,任何在他们的代码中使用我的类的实例的人都会遇到同样的问题,并且需要成为这方面的专家——即使我的类没有在他们的公共接口中公开任何特征类型!
这很令人沮丧。我的问题,
我想使用 Eigen3 库(版本 3.3.2)将元素添加到 Eigen::MatrixXd 对象的对角线上。
为了优化和能够使用常量,我想通过向原始矩阵添加对角矩阵来做到这一点,就像这样
const MatrixXd a(2,2); a << 1, 2, 3, 4;
const VectorXd v(2); v << 10, 20;
const MatrixXd b = a + v.asDiagonal();
Run Code Online (Sandbox Code Playgroud)
但这不起作用:我收到一个关于没有operator+. 添加两个MatrixXd确实有效,所以我希望它对对角线专业化表现得很好。
删除常量无济于事。使用静态大小的矩阵没有区别,所以它不是动态大小的事情。并且显式构造 aDiagonalMatrix而不是使用DiagonalWrapper返回的 byasDiagonal()也会给出相同的错误。
乘法对于这些类型是良构的:MatrixXd c = a * v.asDiagonal();编译和运行都很好。我做错了什么,还是operator+(Matrix,DiagonalMatrix)只是从图书馆里失踪了?