Kronecker产品的可变函数

时间:2016-10-04 17:17:22

标签: c++ variadic-templates variadic-functions

我在构建执行特定任务的可变参数函数时遇到了问题。对于我的特定示例,我使用的是2x2矩阵,但您可以想象我的问题可以归结为许多数据类型。另外,对于我的例子,“眼睛”是2x2单位矩阵。

好的,所以我想构建一个可变参数f,其输入可能是(给出3个例子):

f(Y, 2, Z, 5, X, 3)
f(X, 4)
f(X, 2, Y, 1)

其中X,Y,Z是矩阵,数字是正整数。它应该分别返回以下伪代码kronecker产品:

KroneckerProduct(eye, Y, X, eye, Z)

KroneckerProduct(eye, eye, eye, X)

KroneckerProduct(Y, X)

所以基本上它在矩阵后面的int指定的KroneckerProduct中的位置应用矩阵,并填充其间的标识矩阵。

由于我对可变功能的经验不足,我对此并不了解。我最大的问题是使用可变函数的“递归”步骤来完成我需要的操作(见最后的评论):

template<typename M, typename I, typename... Args>
arma::mat f(M matrix, I position, Args... args) 
{
    std::vector<arma::mat> matrixList;

    while(position > matrixList.size()) 
    {
        matrixList.push_back(eye<arma::mat>(2,2));
    }

    matrixList(position-1) = matrix;

    //Up until here, it's satisfied the first pair of arguments.
    //However, if I call f(args...) now, it'll just re-initialize matrixList
}

我缺少一种解决方法吗?

2 个答案:

答案 0 :(得分:2)

我不知道你将如何计算回报值(我还没有理解那种数学),但是如果你从最终的matrixList计算它,你可以围绕函数做一个包装:

template<typename... Args>
arma::mat calculateSomething(Args&&... args) {
    std::vector<arma::mat> list;
    f(list, std::forward<Args...>(args...)); //First argument for recursion

    //Calculate return value
    return return_value;
 };

f看起来像这样:

//Default case with just 1 argument
void f(std::vector<arma::mat>&) {}

template<typename M, typename I, typename... Ts>
void f(std::vector<arma::mat>& matrixList, M matrix, I position, Ts... args) 
{
    while(position > matrixList.size()) 
    {
        matrixList.push_back(eye<arma::mat>(2,2));
    }

    //This is not valid syntax, no idea what you are trying to do here
    //matrixList(position-1) = matrix;

    //recursive call
    f(matrixList, args...);
}

答案 1 :(得分:1)

建立Rakete1111的建议,这是我打算使用的代码。它会生成k-qubit Heisenberg interactions

#include <iostream>
#include <armadillo>

const arma::cx_mat eye = "(1,0) (0,0); (0,0) (1,0)";
const arma::cx_mat sx = "(0,0) (1,0); (1,0) (0,0)";
const arma::cx_mat sy = "(0,0) (0,-1); (0,1) (0,0)";
const arma::cx_mat sz = "(1,0) (0,0); (0,0) (-1,0)";

void ArgsToMatrixList(std::vector<arma::cx_mat>&) {}

template<typename M, typename I, typename... Ts>
void ArgsToMatrixList(std::vector<arma::cx_mat>& matrixList, M matrix, I position, Ts... args)
{
    while(position > matrixList.size())
    {
        matrixList.push_back(eye);
    }

    matrixList[position - 1] = matrix;

    ArgsToMatrixList(matrixList, args...);
}

template<typename... Args>
arma::cx_mat J(Args&&... args)
{
    std::vector<arma::cx_mat> list;

    ArgsToMatrixList(list, std::forward<Args>(args)...); //First argument for recursion

    //Calculate return value

    arma::cx_mat return_value = list.front();
    for(int i = 1; i < list.size(); ++i)
    {
        return_value = arma::kron(return_value, list[i]);
    }

    return return_value;
}


int main(int argc, const char * argv[]) {

    arma::cx_mat example = J(sx, 1, sy, 2, sz, 3);
    std::cout << example << std::endl;

    return 0;
}