我想实现一个具有张量向量作为成员的C ++类。张量的尺寸不是预定义的,而是根据某些输入数据取值。而且,张量的等级可以不同。像这样:
std::vector< TensorXd > myTensors;
但是,在Eigen中,动态张量没有TensorXd
类型。
为了构建每个张量,我将读取一个数据向量std::vector<double> values
,它代表一个维度n x n x ... x n
(r
次)的张量。像这样:
Tensor<double, r> tensor = TensorMap<double, r>(values.data(), std::vector<size_t>(r, n);
myTensors.push_back(tensor);
有可能吗?
非常感谢您的帮助!
更新
正如Yaroslav Bulatov指出的那样,Eigen不支持动态排名,因此必须明确写出支持的排名。在我的代码中:
#include <iostream>
#include <vector>
#include <Eigen/Dense>
#include <unsupported/Eigen/CXX11/Tensor>
typedef Eigen::Tensor< double , 3 > Tensor3d;
typedef Eigen::Tensor< double , 4 > Tensor4d;
typedef Eigen::Tensor< double , 5 > Tensor5d;
typedef Eigen::Tensor< double , 6 > Tensor6d;
typedef Eigen::Tensor< double , 7 > Tensor7d;
typedef Eigen::Tensor< double , 8 > Tensor8d;
typedef Eigen::Tensor< double , 9 > Tensor9d;
typedef Eigen::Tensor< double , 10 > Tensor10d;
class MyClass
{
private:
Eigen::MatrixXd Potentials_1;
std::vector<Eigen::MatrixXd> Potentials_2;
std::vector< Tensor3d > Potentials_3;
std::vector< Tensor4d > Potentials_4;
std::vector< Tensor5d > Potentials_5;
std::vector< Tensor6d > Potentials_6;
std::vector< Tensor7d > Potentials_7;
std::vector< Tensor8d > Potentials_8;
std::vector< Tensor9d > Potentials_9;
std::vector< Tensor10d > Potentials_10;
public:
MyClass();
void setPotentials_1(const Eigen::MatrixXd &_Potentials_1){ Potentials_1 = _Potentials_1; }
void setPotentials_2(const std::vector<Eigen::MatrixXd> &_Potentials_2){ Potentials_2 = _Potentials_2; }
void setPotentials_3(const std::vector<Tensor3d> &_Potentials_3){ Potentials_3 = _Potentials_3; }
void setPotentials_4(const std::vector<Tensor4d> &_Potentials_4){ Potentials_4 = _Potentials_4; }
void setPotentials_5(const std::vector<Tensor5d> &_Potentials_5){ Potentials_5 = _Potentials_5; }
void setPotentials_6(const std::vector<Tensor6d> &_Potentials_6){ Potentials_6 = _Potentials_6; }
void setPotentials_7(const std::vector<Tensor7d> &_Potentials_7){ Potentials_7 = _Potentials_7; }
void setPotentials_8(const std::vector<Tensor8d> &_Potentials_8){ Potentials_8 = _Potentials_8; }
void setPotentials_9(const std::vector<Tensor9d> &_Potentials_9){ Potentials_9 = _Potentials_9; }
void setPotentials_10(const std::vector<Tensor10d> &_Potentials_10){ Potentials_10 = _Potentials_10; }
};
Yaroslav还建议使用宏可以帮助解决代码重复问题。我不熟悉C ++宏,因此非常感谢任何帮助。
感谢您的帮助!
答案 0 :(得分:2)
您可以查看xtensor C ++模板库,它支持动态和静态维度。
http://xtensor.readthedocs.io/en/latest/
xtensor的API与numpy的API非常相似,包括矢量化,广播,通用功能。这里有xtensor备忘单:http://xtensor.readthedocs.io/en/latest/numpy.html
最后,您可以点击https://github.com/QuantStack/xtensor/顶部的活页夹徽章,在C ++ Jupyter笔记本中试用它。
xtensor还附带了科学计算主要语言(R,Julia,Python)的绑定。
答案 1 :(得分:2)
在我的实现中,我通过使用新的C ++ 17实用程序std :: variant
克服了这个问题。我将其用作 Union Template 。
typedef std::variant<Eigen::Tensor<double, 2>, Eigen::Tensor<double, 3>, /* ... */> TensorOptions;
我定义了上面的特征以便于阅读。
// i is the order of the tensor
TensorOptions makeTensor(const std::size_t& i,const std::initializer_list<int>& dimensions) const
{
int * Arr= new int[i];
std::copy(std::begin(dimensions), std::end(dimensions), Arr);
switch (i) {
case 2: {
Eigen::Tensor<double, 2> T2;
T2.resize(Arr);
return T2;
}
case 3: {
Eigen::Tensor<double, 3> T3;
T3.resize(Arr);
return T3;
}
/* ... */
}
delete [] Arr;
}
int main() {
auto myTensor{makeTensor(2, {4, 5})}; // Tensor 2D 4x5
}
我想指出,要访问这些方法,必须使用std :: visit
。在这里我举几个例子
// Rank
auto rnk = std::visit([](const auto &tensor) { return tensor.rank(); }, myTensor);
// Unfolding
// idxResh and idxSh are dynamic arrays
Eigen::Tensor<double,2> unfolded = std::visit([&idxResh, &idxSh]( auto& tensor) {
// Shuffle
auto tensSh=tensor.shuffle(idxSh);
// Reshape
Eigen::Tensor<double,2> tensResh=tensSh.reshape(idxResh);
return tensResh;},myTensor);