2016-10-04 11 views
0

特定のタスクを実行するバリアント関数を構築する際に問題があります。私の特定の例では、私は2x2行列を使用していますが、私の問題は多くのデータ型に一般化していると想像することができます。また、私の例では、「目」は2x2単位行列です。Kroneckerプロダクト用Variadic関数

[OK]を、私は、その入力(3例を与えるために)かもしれない可変引数関数f構築したい:

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

X、Y、Zは行列であり、数字は正のint値です。それは、それぞれ、以下の疑似コードのクロネッカーの製品を返す必要があります:

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

KroneckerProduct(eye, eye, eye, X) 

KroneckerProduct(Y, X) 

だから、本質的にそれが行列を次の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 
} 

は私が欠けている回避策はありますか?

+0

それはまさに「正常な」再帰関数と同じ回避策です:) – Rakete1111

+0

あなたはmatrixListを宣言した後のものは、別の関数g(STD ::ベクトル&matrixList、引数に置くべきであることを示唆しています... )、g内で再帰を行いますか?限り、私はvariadicテンプレートを理解する限り、gはargsに先行する引数が1つしかないので、引数は一度に1つずつ展開されませんか?私は割り当てを意味のあるものにするために、一度に2つを解凍しておく必要があります。 – user2520385

答えて

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は次のようになります。

Rakete1111の提案をオフに構築
//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...); 
} 
+0

ありがとう、それは働いていますが、私はまだ転送の仕組みを完全に理解していません...私はそれを読み上げる必要があります。完成したコードスニペットを投稿します。 – user2520385

1

を、私はそれが動作するように意図したように、これはコードです。それは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; 
} 
関連する問題