2016-10-04 1 views
0

J'ai des difficultés à construire une fonction variadique qui effectue une tâche particulière. Pour mon exemple particulier, j'utilise des matrices 2x2 mais vous pouvez imaginer que mon problème se généralise à de nombreux types de données. Aussi, pour mon exemple, "oeil" est la matrice d'identité 2x2.Fonction variadique pour produit Kronecker

Ok, alors je voudrais construire une fonction variadic f dont les entrées peuvent être (pour donner 3 exemples):

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

où X, Y, Z sont des matrices, et les chiffres sont ints positifs. Elle doit retourner les produits de Kronecker pseudo-code suivant respectivement:

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

KroneckerProduct(eye, eye, eye, X) 

KroneckerProduct(Y, X) 

Donc, essentiellement, il applique une matrice à la position dans le produit de kronecker spécifié par l'int qui suit la matrice, et les remplissages dans des matrices entre identité. En raison de mon inexpérience avec les fonctions variées, je ne suis pas allé loin avec ça. Mon plus gros problème est d'étape récursif de la fonction variadique faire ce que je dois (voir les commentaires à la fin):

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 
} 

Y at-il une solution de contournement que je suis absent?

+0

Il est exactement la même solution en fonction récursive « normale » :) – Rakete1111

+0

suggérez-vous que les choses après avoir déclaré matrixList devrait être mis dans une autre fonction g (std :: vecteur & matrixList, args ...), et faire une récursion dans g? Dans la mesure où je comprends les modèles variadiques, puisque g n'a qu'un seul argument précédant les arguments ..., les arguments ne seraient-ils pas déballés un à la fois? J'ai besoin d'eux déballés deux à la fois pour que les devoirs aient du sens. – user2520385

Répondre

2

Je ne sais pas comment vous allez calculer la valeur de retour (je ne comprends pas encore ce type de calcul), mais si vous le calculez à partir de la dernière matrixList, vous pouvez faire un wrapper autour de la fonction:

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

Et f ressemblerait à ceci:

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

Merci, ça a marché, même si je ne comprends toujours pas comment fonctionne le transfert ... J'ai besoin de lire dessus. Je posterai l'extrait de code terminé. – user2520385

1

S'appuyant sur les suggestions de Rakete1111, c'est le code que je comptais faire fonctionner. Il génère 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; 
}