N'utilisez pas la méthode swap, c'est très inefficace. Et la réponse de l'autre personne est spécifique à la porte CNOT, et pour être franc, complique trop les choses.
Voici un algorithme très simple qui résout votre problème pour chaque cas, pas seulement la porte CNOT, pour tous les bits arbitraires.
L'algorithme:
let sys = matrix representing the current state of the system
let n = number of qubits being simulated
let lgm = logic gate matrix of size 2^n by 2^n
let f = our logic gate transformation function
for i = 0 to (2^n) - 1:
lgm[column = i] = f(i)
sys = sys × lgg
Dans les ordinateurs classiques, il y a quelque chose connu comme le "décodeur". Disons que je n'ai que 3 fils, en fait, 3 bits. Mais je veux contrôler 8 fils. Cela peut-il être fait? Oui, car 3 bits ont 8 possibilités différentes: 000, 001, 010, 011, 100, 101, 110, 111. Nous pouvons donc attribuer chaque possibilité à l'un de nos 8 fils de sortie. C'est ce qu'on appelle le «décodage».
Si je passe le nombre 101 et que nous avons 3 bits, nous savons que 101 = 5, alors je mettrai le fil de sortie 5 à une tension élevée et les 7 autres fils de sortie seront 0, que nous pouvons représenter comme ceci: décoder (101) = [0, 0, 0, 0, 0, 1, 0, 0].
Dans cet algorithme, je mentionne la "fonction de transformation" appelée "f". Pour les ordinateurs classiques, la fonction de transformation prend simplement une valeur d'entrée et renvoie la version "décodée" de la valeur de sortie. Donc, si nous avons 3 bits et que la sortie est 4, alors nous retournerons [0, 0, 0, 0, 1, 0, 0, 0]. Nous attribuons ensuite cela comme colonne de notre matrice pour cette valeur.
Pensons au "décodage" en termes de qubits. Comment décoder les qubits | 101>?
Nous savons que pour nos vecteurs de probabilité qubit, | 0> est [1, 0] et | 1> est [0, 1]. Le décodage des qubits peut alors être fait ce qu'on appelle le produit Kronecker.
Donc, si nous convertissons chaque bit en équivalent de vecteur de probabilité et prenons le produit Kronecker de chacun d'eux, nous obtenons ...
|101> = |1> ⊗ |0> ⊗ |1> = [0, 1] ⊗ [1, 0] ⊗ [0, 1] = [0, 0, 0, 0, 0, 1, 0, 0]
C'est ainsi que nous voudrions décoder les qubits. Cet algorithme peut être appliqué aux qubits de la même manière en utilisant ceci.
Essayons cet algorithme sur un problème plus simple.
Supposons que nous ayons un système avec seulement 2 qubits. Si nous voulons appliquer la porte Hadamard à seulement 1 qubit, nous pouvons générer une porte logique pour les deux qubits qui n'applique la porte Hadamard qu'à un seul qubit. Supposons que le qubit unique auquel nous voulons l'appliquer soit notre qubit le plus significatif et que le moins significatif ne soit pas affecté.
Nous voulons une fonction de transformation qui, pour chacune de nos entrées possibles, produise la sortie correcte. Nous avons deux qubits, cela signifie qu'il y a quatre sorties possibles.
f(|00>) = ?
f(|01>) = ?
f(|10>) = ?
f(|11>) = ?
Nous savons que le qubit le moins significatif ne sera pas affecté, nous pouvons donc le remplir.
f(|00>) = ? ⊗ |0>
f(|01>) = ? ⊗ |1>
f(|10>) = ? ⊗ |0>
f(|11>) = ? ⊗ |1>
Nous savons également ce que le Hadamard fait à un qubit, de sorte que:
H(|0>) = 1/sqrt(2)|0> + 1/sqrt(2)|1>
H(|1>) = 1/sqrt(2)|0> - 1/sqrt(2)|1>
Notre fonction de transformation est donc simplement:
f(|00>) = (1/sqrt(2)|0> + 1/sqrt(2)|1>) ⊗ |0>
f(|01>) = (1/sqrt(2)|0> + 1/sqrt(2)|1>) ⊗ |1>
f(|10>) = (1/sqrt(2)|0> - 1/sqrt(2)|1>) ⊗ |0>
f(|11>) = (1/sqrt(2)|0> - 1/sqrt(2)|1>) ⊗ |1>
Développez cela à notre forme vectorielle de probabilité normalisée ...
f(|00>) = [ 1/sqrt(2), 1/sqrt(2) ] ⊗ [ 1, 0 ]
f(|01>) = [ 1/sqrt(2), 1/sqrt(2) ] ⊗ [ 0, 1 ]
f(|10>) = [ 1/sqrt(2), -1/sqrt(2) ] ⊗ [ 1, 0 ]
f(|11>) = [ 1/sqrt(2), -1/sqrt(2) ] ⊗ [ 0, 1 ]
Maintenant, résolvons réellement cela ...
f(|00>) = [ 1/sqrt(2), 0, 1/sqrt(2), 0 ]
f(|01>) = [ 0, 1/sqrt(2), 0, 1/sqrt(2) ]
f(|10>) = [ 1/sqrt(2), 0, -1/sqrt(2), 0 ]
f(|11>) = [ 0, 1/sqrt(2), 0, -1/sqrt(2) ]
C'est notre fonction de transformation.
Notre matrice de portes logiques, "lgm", est de taille 2 ^ n par 2 ^ n où n = nombre de qubits simulés, donc dans ce cas, c'est 2 ^ 2 par 2 ^ 2 ou 4x4. Notre algorithme nous dit que pour chaque colonne i, définissez la colonne égale à f (i). Nous avons défini notre fonction de transformation de probabilité, afin que nous puissions facilement remplir ces colonnes.
lgm =
|00> |01> |10> |11>
[ 1/sqrt(2), 0, 1/sqrt(2), 0 ]
[ 0, 1/sqrt(2), 0, 1/sqrt(2) ]
[ 1/sqrt(2), 0, -1/sqrt(2), 0 ]
[ 0, 1/sqrt(2), 0, -1/sqrt(2) ]
Maintenant, la dernière étape de notre algorithme consiste simplement à multiplier par matrice notre matrice représentant l'ensemble du système quantique, sys, par cette porte logique, lgm.
Et c'est ce que nous voulons. Il appliquera la porte hadamard uniquement au qubit le plus élevé et laissera le qubit le moins significatif seul. Si vous ne me croyez pas, vous pouvez l'essayer vous-même et voir que cela fonctionne.
La raison pour laquelle cela est si puissant est qu'il s'applique à tous les cas.
Essayons cet algorithme sur votre problème.
Imaginez que nous avons un système à 3 qubits et que nous voulons appliquer une porte CNOT à qubit [0] et qubit [2]. Si vous recherchez la matrice CNOT sur Wikipedia, cette matrice ne s'applique qu'à un système à 2 qubits. Une solution naïve serait d'y ajouter des matrices d'identité en utilisant le produit Kronecker pour le faire fonctionner sur des systèmes à trois qubits. Mais cela échoue ici: qubit [0] et qubit [2] ne sont pas adjacents, donc simplement ajouter des matrices d'identité ne fonctionnera pas.
Nous pourrions échanger qubit [0] avec qubit [1], appliquer la porte CNOT, puis les échanger à nouveau. Mais c'est lent. Au lieu de cela, nous pourrions simplement générer une porte CNOT non adjacente pour notre problème en utilisant l'algorithme ci-dessus.
Nous devons d'abord trouver une fonction de transformation pour chaque cas.
f(|000>) = |0> ⊗ |0> ⊗ |0>
f(|001>) = |0> ⊗ |0> ⊗ |1>
f(|010>) = |0> ⊗ |1> ⊗ |0>
f(|011>) = |0> ⊗ |1> ⊗ |1>
f(|100>) = |1> ⊗ |0> ⊗ |1>
f(|101>) = |1> ⊗ |0> ⊗ |0>
f(|110>) = |1> ⊗ |1> ⊗ |1>
f(|111>) = |1> ⊗ |1> ⊗ |0>
Si vous comprenez la porte CNOT, vous pouvez comprendre pourquoi c'est notre fonction. Pensez à cela comme une table de vérité. Puisque notre qubit de contrôle est le qubit le plus significatif, qubit [2], ce n'est que lorsque ce qubit est | 1> que le qubit le moins significatif, qubit [0], sera annulé.
Développez cela à notre forme vectorielle de probabilité normalisée ...
f(|000>) = [ 1, 0 ] ⊗ [ 1, 0 ] ⊗ [ 1, 0 ]
f(|001>) = [ 1, 0 ] ⊗ [ 1, 0 ] ⊗ [ 0, 1 ]
f(|010>) = [ 1, 0 ] ⊗ [ 0, 1 ] ⊗ [ 1, 0 ]
f(|011>) = [ 1, 0 ] ⊗ [ 0, 1 ] ⊗ [ 0, 1 ]
f(|100>) = [ 0, 1 ] ⊗ [ 1, 0 ] ⊗ [ 0, 1 ]
f(|101>) = [ 0, 1 ] ⊗ [ 1, 0 ] ⊗ [ 1, 0 ]
f(|110>) = [ 0, 1 ] ⊗ [ 0, 1 ] ⊗ [ 0, 1 ]
f(|111>) = [ 0, 1 ] ⊗ [ 0, 1 ] ⊗ [ 1, 0 ]
Maintenant, résolvons réellement cela ...
f(|000>) = [ 1, 0, 0, 0, 0, 0, 0, 0 ]
f(|001>) = [ 0, 1, 0, 0, 0, 0, 0, 0 ]
f(|010>) = [ 0, 0, 1, 0, 0, 0, 0, 0 ]
f(|011>) = [ 0, 0, 0, 1, 0, 0, 0, 0 ]
f(|100>) = [ 0, 0, 0, 0, 0, 1, 0, 0 ]
f(|101>) = [ 0, 0, 0, 0, 1, 0, 0, 0 ]
f(|110>) = [ 0, 0, 0, 0, 0, 0, 0, 1 ]
f(|111>) = [ 0, 0, 0, 0, 0, 0, 1, 0 ]
Faisons-en les colonnes de notre matrice lgm.
lgm =
[ 1, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 1, 0, 0, 0, 0, 0, 0 ]
[ 0, 0, 1, 0, 0, 0, 0, 0 ]
[ 0, 0, 0, 1, 0, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 1, 0, 0 ]
[ 0, 0, 0, 0, 1, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 1 ]
[ 0, 0, 0, 0, 0, 0, 1, 0 ]
Maintenant, si la matrice multiplie notre matrice système entière, sys, par notre matrice de porte logique, lgm, notre résultat sera l'effet de l'application de la porte CNOT à qubit [2] et qubit [0] où qubit [2] est le contrôle qubit.