Eigen unaryExpr():获取元素的索引
Eigen unaryExpr(): get index of element
我知道在 Eigen 中我可以使用 unaryExpr()
将自定义函数应用于我的 Eigen 矩阵和向量,例如
Eigen::VectorXd vec(4);
vec.unaryExpr([](double d) {
return d * cos(d);
});
将自定义函数应用于 Eigen::VectorXd
。但是还有一种方法可以获取当前元素在我的 Vector 中的位置吗?我希望能够做这样的事情:
Eigen::VectorXd vec(4);
vec.unaryExpr([](double d, int index) {
return index * d;
});
例如,将向量中的每个条目乘以它的位置。
你打算做的只是一个普通的for循环:
for (int i = 0; i < vec.size(); ++i)
vec(i) *= i;
那为什么不让事情简单点呢?如果它应该可用于创建对象,请将其包装在辅助函数(模板)中。
此外,您可以做的是依赖Eigen的内部求值顺序。这似乎可行,但我不确定我是否会依赖它:
struct CountingUnaryFct {
double operator()(double d) const { return d*index++; }
mutable int index = 0;
};
vec.unaryExpr(CountingUnaryFct{});
这是一个相当丑陋的 hack,因为它欺骗了 unaryExpr
模板,该模板要求其函数对象具有 const
合格的成员 operator()(double) const
(不可能使用 mutable
-lambda,因此是函数对象)来接受一个实际上确实在幕后改变其状态的实例。但同样,它似乎可以可靠地工作,至少在一维矩阵上是这样。
您可以使用空表达式解决问题:
VectorXd v;
v = VectorXd::NullaryExpr([&v](Index i) { return v(i)*i; });
你几乎可以用空表达式做任何事情:https://eigen.tuxfamily.org/dox/TopicCustomizing_NullaryExpr.html
除了按照@ggael 的建议使用零表达式外,您还可以将二进制表达式与 LinSpaced(size, 0, size-1)
:
一起使用
VectorXd v; // some input vector
v = v.binaryExpr(VectorXd::LinSpaced(v.size(), 0, v.size()-1),
[](double d, double i){return d*i;});
// or much simpler and more efficient in this case:
v = v.cwiseProduct(VectorXd::LinSpaced(v.size(), 0, v.size()-1));
在足够新的 Eigen 版本上,LinSpaced
应该被矢量化(尽管关于最后一个元素有一些边界情况)。 binaryExpr
当然,只有在传递的仿函数被矢量化时才会被矢量化。
N.B.: 如果你主要做元素操作,考虑使用 ArrayXd
而不是 VectorXd
.
我知道在 Eigen 中我可以使用 unaryExpr()
将自定义函数应用于我的 Eigen 矩阵和向量,例如
Eigen::VectorXd vec(4);
vec.unaryExpr([](double d) {
return d * cos(d);
});
将自定义函数应用于 Eigen::VectorXd
。但是还有一种方法可以获取当前元素在我的 Vector 中的位置吗?我希望能够做这样的事情:
Eigen::VectorXd vec(4);
vec.unaryExpr([](double d, int index) {
return index * d;
});
例如,将向量中的每个条目乘以它的位置。
你打算做的只是一个普通的for循环:
for (int i = 0; i < vec.size(); ++i)
vec(i) *= i;
那为什么不让事情简单点呢?如果它应该可用于创建对象,请将其包装在辅助函数(模板)中。
此外,您可以做的是依赖Eigen的内部求值顺序。这似乎可行,但我不确定我是否会依赖它:
struct CountingUnaryFct {
double operator()(double d) const { return d*index++; }
mutable int index = 0;
};
vec.unaryExpr(CountingUnaryFct{});
这是一个相当丑陋的 hack,因为它欺骗了 unaryExpr
模板,该模板要求其函数对象具有 const
合格的成员 operator()(double) const
(不可能使用 mutable
-lambda,因此是函数对象)来接受一个实际上确实在幕后改变其状态的实例。但同样,它似乎可以可靠地工作,至少在一维矩阵上是这样。
您可以使用空表达式解决问题:
VectorXd v;
v = VectorXd::NullaryExpr([&v](Index i) { return v(i)*i; });
你几乎可以用空表达式做任何事情:https://eigen.tuxfamily.org/dox/TopicCustomizing_NullaryExpr.html
除了按照@ggael 的建议使用零表达式外,您还可以将二进制表达式与 LinSpaced(size, 0, size-1)
:
VectorXd v; // some input vector
v = v.binaryExpr(VectorXd::LinSpaced(v.size(), 0, v.size()-1),
[](double d, double i){return d*i;});
// or much simpler and more efficient in this case:
v = v.cwiseProduct(VectorXd::LinSpaced(v.size(), 0, v.size()-1));
在足够新的 Eigen 版本上,LinSpaced
应该被矢量化(尽管关于最后一个元素有一些边界情况)。 binaryExpr
当然,只有在传递的仿函数被矢量化时才会被矢量化。
N.B.: 如果你主要做元素操作,考虑使用 ArrayXd
而不是 VectorXd
.