C++ 特征:动态张量 [英] C++ Eigen: dynamic tensor

查看:69
本文介绍了C++ 特征:动态张量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现一个 C++ 类,它有一个张量向量作为成员.张量的维度不是预定义的,而是根据一些输入数据取值.此外,张量的等级可以不同.像这样:

I would like to implement a C++ class that has a vector of tensors as member. The dimensions of the tensors are not predefined but will take values according to some input data. Moreover, the ranks of the tensors can be different. Something like this:

std::vector< TensorXd > myTensors;

Eigen,但是,动态张量没有这样的 TensorXd 类型.

In Eigen, however, there is no such TensorXd type for dynamic tensors.

为了构建每个张量,我将读取一个数据向量 std::vector;values 表示维度 n x n x ... x n(r 次)的张量.像这样:

For constructing each tensor, I will read a vector of data std::vector<double> values that represents a tensor of dimension n x n x ... x n (r times). Something like this:

Tensor<double, r> tensor = TensorMap<double, r>(values.data(), std::vector<size_t>(r, n);
myTensors.push_back(tensor);

能做到吗?

非常感谢您的帮助!

更新:

正如 Yaroslav Bulatov 指出的那样,Eigen 不支持动态排名,因此必须明确写出支持的排名.在我的代码中:

As Yaroslav Bulatov pointed out, Eigen does not support dynamic rank and thus the supported ranks have to be written out explicitly. In my code:

#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++ 宏,因此非常感谢您的帮助.

Yaroslav also suggested that using macros can help to void code duplication. I'm not familiar with C++ macros, thus any help would be very appreciated.

感谢您的帮助!

推荐答案

在我的实现中,我通过使用新的 C ++ 17 实用程序 std :: variant 克服了这个问题;我用它作为联合模板.

In my implementation I have overcome the problem by using a new C ++ 17 utility, std :: variant; I used it as Union Template.

typedef std::variant<Eigen::Tensor<double, 2>, Eigen::Tensor<double, 3>, /* ... */> TensorOptions;

我在上面定义了 trait 以便于阅读.

I defined the trait above for easier reading.

// 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.这里我报告几个例子

I want to point out that to access the methods it is necessary to use std :: visit. Here I report a couple of examples

// 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);

这篇关于C++ 特征:动态张量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆