Kronecker积的变函数

Variadic Function for Kronecker Product

本文关键字:函数 Kronecker      更新时间:2023-10-16

我在构造一个执行特定任务的可变函数时遇到了麻烦。对于我的特殊例子,我使用2x2矩阵,但你可以想象,我的问题推广到许多数据类型。同样,在我的例子中,"eye"是2x2单位矩阵。

好的,所以我想构造一个可变函数f,它的输入可能是(举三个例子):

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)

所以本质上它在KroneckerProduct中的位置应用一个矩阵,这个矩阵是由矩阵后面的int指定的,并填充中间的单位矩阵

由于我对可变函数缺乏经验,我还没有深入了解它。我最大的问题是得到可变函数的"递归"步骤来做我需要的(见最后的注释):

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
}

是否有我遗漏的变通方法?

我不知道你将如何计算返回值(我不理解那种数学),但如果你从最终的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...);
}

根据Rakete1111的建议,这是我希望它工作的代码。它产生k-量子位海森堡相互作用。

#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;
}