[PYTHON] Bases de la théorie de l'information quantique: calcul quantique tolérant aux pannes

\def\bra#1{\mathinner{\left\langle{#1}\right|}} \def\ket#1{\mathinner{\left|{#1}\right\rangle}} \def\braket#1#2{\mathinner{\left\langle{#1}\middle|#2\right\rangle}}

introduction

Jusqu'au précédent, j'ai pu comprendre le "code de correction d'erreur". Avec cela, même si du bruit est ajouté à l'ordinateur quantique, l'erreur peut être corrigée et le résultat du calcul peut être obtenu correctement! J'aimerais dire (du moins en théorie!), Mais ce n'est pas du tout! J'en parlerai à partir de maintenant. Le bruit peut se produire n'importe où dans le processus de calcul quantique, et un traitement spécial est requis pour chacun d'eux. On peut dire que le calcul quantique tolérant aux pannes, qui est tolérant aux erreurs et fonctionne correctement même s'il y a des erreurs, n'a été réalisé qu'après leur mise en œuvre.

Permettez-moi d'abord de dire ce que j'essaie d'expliquer dans les sections qui suivent. Tout d'abord, dans «l'explication de la théorie», après avoir expliqué ce que signifie être tolérant aux pannes, nous introduirons des portes quantiques et des méthodes concrètement tolérantes aux pannes pour réaliser la mesure et la création de l'état initial, puis relierons les codes et le théorème de seuil. Cette section explique. Dans "Operation check", nous prendrons un exemple très simple de calcul quantique tolérant aux pannes et vérifierons son fonctionnement à l'aide du simulateur de calcul quantique qlazy.

Les documents suivants ont été utilisés comme références.

  1. Neilsen, Chan "Quantum Computer and Quantum Communication (3)" Ohm (2005)

Explication de la théorie

Définition de la tolérance aux pannes

Le code de correction d'erreur correspond au bruit généré lorsque l'état quantique est stocké et transmis. Etant donné que le calcul quantique réel consiste en une série de processus tels que "création d'état initial", "opération de porte" et "mesure", le code de correction d'erreur seul ne suffit pas. Par exemple, comment effectuez-vous une opération de portail? Ne devrions-nous pas simplement décoder l'état codé une fois, exécuter l'opération de porte, puis l'encoder à nouveau immédiatement? Vous pourriez penser, mais l'idée n'est pas bonne. Le bruit peut être mélangé pendant le processus de décodage et d'encodage et les opérations de porte. Par conséquent, une meilleure façon est d'effectuer l'opération de porte dans l'état codé, mais il ne suffit pas de configurer simplement la porte de sorte qu'elle n'ait pas besoin d'être décodée. Il doit être configuré pour que le bruit généré quelque part ne se propage et ne se multiplie pas. Par exemple, la porte de contrôle NOT (porte CNOT) est une porte très utile dans toutes les situations, mais si $ U_ {1,2} $ est l'opération de contrôle NOT, $ U_ {1,2} X_ {1} = X_ {1} Puisque X_ {2} U_ {1,2} $ tient, le bruit d'inversion de bit généré du côté contrôle de l'entrée se propage à la fois du côté contrôle et du côté cible de la sortie. D'un autre côté, $ U_ {1,2} Z_ {2} = Z_ {1} Z_ {2} U_ {1,2} $ est valable, donc le bruit d'inversion de phase généré du côté cible d'entrée est le côté commande de sortie et cible. Propagez sur le côté. Si vous l'écrivez dans un diagramme, il se propagera comme suit.

<Inversion de bits côté commande[X]Propage pour contrôler / cibler>

--[X]--*----     ----*--[X]--
       |      =>     |
-------X----     ----X--[X]--


<Inversion de phase côté cible[Z]Propage pour contrôler / cibler>

-------*----     ----*--[Z]--
       |      =>     |
--[Z]--X----     ----X--[Z]--

Ce serait très mauvais s'il y avait une telle partie dans l'opération de porte pour l'état codé. La correction d'erreur est possible si elle se produit une seule fois dans un bloc de code, mais avec la configuration ci-dessus, un bruit augmente à deux, ce qui rend impossible la correction. Par conséquent, il doit être configuré pour éviter que cela ne se produise. En outre, non seulement le calcul de la porte mais également la procédure de correction d'erreur elle-même peuvent générer du bruit, cette contre-mesure est donc également nécessaire. De plus, le bruit peut être mélangé au processus de création et de mesure de l'état initial.

Et ainsi de suite, je sens peu à peu que la tolérance aux fautes est impossible. Parce que CNOT propage le bruit. Est-il possible de réaliser CNOT pour l'état du code sans utiliser CNOT? Est-il possible de corriger des erreurs sans CNOT? Mais ne t'inquiète pas. En fait, cela ne signifie pas que vous ne devriez jamais utiliser CNOT. Il n'y a pas de problème si la propagation remplit certaines conditions. La condition (= définition de la tolérance aux pannes) est "lorsqu'un bruit se produit dans le système qui exécute le calcul quantique, au plus un bruit est généré dans chaque bloc de code. ". Puisqu'un bruit par bloc de code peut être corrigé, la propagation vers le même bloc de code où le bruit s'est produit n'est pas bonne (car il y a deux bruits par bloc), mais propagation vers d'autres blocs Est autorisé (car un bruit peut être corrigé). Si le système informatique quantique est configuré de cette manière, on peut dire qu'il est tolérant aux pannes.

Malheureusement, le bruit peut se produire à plusieurs endroits en même temps [^ 1]. Et, malheureusement, la propagation peut entraîner deux bruits dans le même bloc de code. Dans ce cas, le résultat du calcul sera incorrect. Cependant, la probabilité doit être réduite à au plus $ O (p ^ {2}) $, en supposant que la probabilité que le bruit se produise à un endroit soit $ p $. Ceci est manifestement tolérant aux pannes, car la probabilité d'un mauvais calcul est $ O (p) $ et ce sera $ O (p ^ {2}) $ si aucune action n'est prise sur l'erreur. C'est un effet. En d'autres termes, le fait que le taux d'erreur de calcul soit au plus $ O (p ^ {2}) $ peut être considéré comme l'une des caractéristiques du calcul quantique tolérant aux pannes.

[^ 1]: "Simultanément" signifie qu'un autre bruit est généré avant que la correction d'erreur ne soit exécutée pour un bruit (je pense).

Structure du calcul quantique tolérant aux pannes

Voyons maintenant comment le «calcul de porte», la «mesure» et la «création de l'état initial» peuvent être configurés comme tolérants aux pannes. Comme il est plus facile de penser avec le code Steane de 7 bits quantiques, toutes les discussions suivantes supposent le code Steane [^ 2].

[^ 2]: Dans le cas d'un code à 5 bits quantiques, il est assez difficile de rendre le fonctionnement de la porte tolérant aux pannes. Cependant, il semble que $ X $ et $ Z $ puissent être transformés dans le type transversal qui sera expliqué plus tard, alors n'est-ce pas si difficile? Je le sens, mais je pense qu'il y a un mur dans un endroit que je n'ai pas encore compris, peut-être parce que je fais une terrible erreur. Ce sera mon futur devoir de penser à la tolérance aux erreurs avec 5 bits quantiques.

Calcul de la porte

Pauligate: X, Y, Z

Commencez par Pauli $ Z $. La logique de code Steane $ Z $ est interchangeable avec les six sources.

\bar{Z} = Z_{1} Z_{2} Z_{3} Z_{4} Z_{5} Z_{6} Z_{7}  \tag{1}

Peut être défini comme. La source est

La source opérateur
g_1 I \space I \space I \space X \space X \space X \space X
g_2 I \space X \space X \space I \space I \space X \space X
g_3 X \space I \space X \space I \space X \space I \space X
g_4 I \space I \space I \space Z \space Z \space Z \space Z
g_5 I \space Z \space Z \space I \space I \space Z \space Z
g_6 Z \space I \space Z \space I \space Z \space I \space Z

Ainsi, vous pouvez voir que la définition de l'équation (1) est bonne [^ 3].

[^ 3]: Le même opérateur s'écrit $ X_ {1} Z_ {2} X_ {3} $, $ X \ otimes Z \ otimes X $, ou $ XZX $, mais la substance est C'est la même chose alors ne vous trompez pas

L'état du stabilisateur uniquement déterminé par les 7 opérateurs, qui est l'addition de $ \ bar {Z} $ aux 6 générateurs, est $ \ ket {0_L} $, et $ \ bar {Z} $ est $ - \ bar { Soit $ \ ket {1_L} $ l'état du stabilisateur qui est déterminé uniquement lors du passage à Z} $. Puis

\bar{Z} \ket{0_L} = \ket{0_L}, \space \bar{Z} \ket{1_L} = - \ket{1_L}  \tag{2}

Et si $ \ bar {Z} $ est exprimé par la base logique $ \ {\ ket {0_L}, \ ket {1_L} \} $,

\bar{Z} = 
\begin{pmatrix}
1 & 0\\
0 & -1
\end{pmatrix}  \tag{3}

Cela vous semblera familier. Jusqu'à présent, il s'agit d'un examen pour vous rappeler ce que vous avez fait lorsque vous avez utilisé le code de correction d'erreur. Ce à quoi je voudrais faire attention ici, c'est la forme de l'équation (1). Lorsqu'il est écrit dans un circuit quantique,

--Z--
--Z--
--Z--
--Z--
--Z--
--Z--
--Z--

Ce sera. Comme vous pouvez le voir, cela consiste à effectuer une opération $ Z $ bit par bit, de sorte que le bruit dans n'importe quel bit n'affecte pas les autres bits du bloc de code. La propriété qu'une porte codée peut réaliser par une opération de porte bit par bit est appelée "transversalité", et on peut immédiatement dire qu'il s'agit d'une opération de porte tolérante aux fautes.

Vient ensuite Pauli $ X $.

\bar{X} \bar{Z} \bar{X} = -\bar{Z}  \tag{4}

Tout ce que vous avez à faire est de décider $ \ bar {X} $ à satisfaire. Par exemple

\bar{X} = X_{1} X_{2} X_{3} X_{4} X_{5} X_{6} X_{7}  \tag{5}

Tu peux y aller. Puis

\bar{X} \ket{0_L} = \ket{1_L}, \space \bar{X} \ket{1_L} = \ket{0_L}  \tag{6}

Donc [^ 4], la représentation matricielle dans la base logique est

[^ 4]: $ \ bar {X} \ ket {0_L} = \ bar {X} \ bar {Z} \ ket {0_L} = - \ bar {Z} \ bar {X} \ ket {0_L} $ Donc $ \ bar {X} \ ket {0_L} $ est un état unique pour la valeur unique $ -1 $ de $ \ bar {Z} $. Autrement dit, $ \ bar {X} \ ket {0_L} = \ ket {1_L} $. Calculer $ \ bar {X} $ des deux côtés donne $ \ bar {X} \ ket {1_L} = \ ket {0_L} $. Dans le détail, il semble que la définition de $ \ bar {X} \ ket {0_L} = e ^ {i \ alpha} \ ket {1_L} $ soit correcte, mais $ \ alpha = 0 $ Je pense que c'est une pratique.

\bar{X} =
\begin{pmatrix}
0 & 1\\
1 & 0
\end{pmatrix}  \tag{7}

est. Comme vous pouvez le voir sur la forme de l'équation (5), il s'agit également d'un type transversal, ce qui signifie qu'un Pauli $ X $ tolérant aux pannes a été réalisé.

Pour Pauli $ Y $,

\bar{Y} = i\bar{X}\bar{Z} = Y_{1} Y_{2} Y_{3} Y_{4} Y_{5} Y_{6} Y_{7}  \tag{8}

Si vous le définissez comme, tout rentrera dans un cercle. Autrement dit, $ \ bar {Y} $ est contre-convertible en $ \ bar {X} $ et $ \ bar {Z} $, et $ \ bar {Y} $ devient lui-même Elmeet.

\bar{Y}\ket{0_L} = -i\ket{1_L}, \space \bar{Y}\ket{1_L} = i\ket{0_L} \tag{9}

La représentation matricielle est donc

\bar{Y} =
\begin{pmatrix}
0 & -i\\
i & 0
\end{pmatrix}  \tag{10}

Ce sera. L'équation (8) étant de type transversal, cela signifie qu'un Pauli $ Y $ tolérant aux fautes a été réalisé.

Porte Adamal: H

Sur la base de $ \ bar {X}, \ bar {Y}, \ bar {Z} $, configurons la porte Adamar pour l'état de signe en tant que tolérance aux pannes.

\bar{H} \bar{X} \bar{H} = \bar{Z}, \space \bar{H} \bar{Z} \bar{H} = \bar{X}  \tag{11}

J'ai juste besoin de décider $ \ bar {H} $ qui satisfait

\bar{H} = H_{1} H_{2} H_{3} H_{4} H_{5} H_{6} H_{7}  \tag{12}

Vous pouvez voir que l'équation (11) est satisfaite.

\begin{align}
\bar{H}\ket{0_L} &= \bar{H}\bar{Z}\ket{0_L} = \bar{X}\bar{H}\ket{0_L} \\
\bar{H}\ket{1_L} &= -\bar{H}\bar{Z}\ket{1_1} = -\bar{X}\bar{H}\ket{1_L} \tag{13}
\end{align}

Comme vous pouvez le voir, $ \ bar {H} \ ket {0_L} $ est l'état propre de $ \ bar {X} $ et $ \ bar {H} \ ket {1_L} $ est l'état propre de $ \ Valeur unique de la barre {X} $ L'état unique de $ -1 $. Par conséquent, chacun

\begin{align}
\bar{H}\ket{0_L} &= \frac{1}{\sqrt{2}} (\ket{0_L} + \ket{1_L}) \\
\bar{H}\ket{1_L} &= \frac{1}{\sqrt{2}} (\ket{0_L} - \ket{1_L}) \tag{14}
\end{align}

La représentation matricielle peut être écrite comme

\bar{H} = \frac{1}{\sqrt{2}}
\begin{pmatrix}
1 & 1\\
1 & -1
\end{pmatrix}  \tag{15}

Ce sera. Comme vous pouvez le voir à partir de l'équation (12), il s'agit d'un type transversal, cela signifie donc qu'une porte Adamal tolérante aux fautes a été réalisée.

Porte de décalage de phase: S
\bar{S}\bar{X}\bar{S}^{\dagger} = \bar{Y}, \space \bar{S}\bar{Z}\bar{S}^{\dagger} = \bar{Z} \tag{16}

Déterminez $ \ bar {S} $ à rencontrer.

\bar{S} = S_{1} S_{2} S_{3} S_{4} S_{5} S_{6} S_{7}  \tag{17}

Je pense un instant que je peux y aller, mais avec cela, l'équation (16) ne tient pas.

\bar{S} = (Z_{1}S_{1}) (Z_{2}S_{2}) (Z_{3}S_{3}) (Z_{4}S_{4}) (Z_{5}S_{5}) (Z_{6}S_{6}) (Z_{7}S_{7})  \tag{18}

Si c'est le cas, c'est OK (je pense que vous pouvez facilement le vérifier). La représentation matricielle pour satisfaire l'équation (16) est

\bar{S} =
\begin{pmatrix}
1 & 0\\
0 & i
\end{pmatrix}  \tag{19}

(Je pense que vous pouvez facilement vérifier cela aussi). Comme vous pouvez le voir à partir de l'équation (18), il s'agit d'un type transversal, ce qui signifie qu'une porte de déphasage tolérante aux pannes a été réalisée.

Je ne pense pas que je vais faire une erreur, mais si j'écris un schéma de circuit au cas où,

--S-Z--
--S-Z--
--S-Z--
--S-Z--
--S-Z--
--S-Z--
--S-Z--

est. Il est de notoriété publique dans l'industrie que l'ordre des opérateurs lorsqu'ils sont écrits dans des formules mathématiques et l'ordre des opérateurs lorsqu'ils sont écrits dans des schémas de circuit sont inversés, mais si vous l'implémentez par inadvertance de manière incorrecte (vous-même). Est la sueur).

Contrôle PAS de porte: CNOT

Maintenant, la porte de contrôle PAS en question. Est-il possible de le configurer pour qu'il ne se propage pas dans le même bloc de code? Nous écrirons $ \ bar {U} _ {A, B} $ comme opérateur de contrôle NOT pour l'état de code où le bloc de code $ A $ est considéré comme le bit de contrôle et le bloc de code $ B $ est considéré comme le bit cible. En ce moment,

\begin{align}
\bar{U}_{A,B} \bar{X_A} \bar{U}_{A,B} &= \bar{X_A} \bar{X_B} \\
\bar{U}_{A,B} \bar{X_B} \bar{U}_{A,B} &= \bar{X_B} \\
\bar{U}_{A,B} \bar{Z_A} \bar{U}_{A,B} &= \bar{Z_A} \\
\bar{U}_{A,B} \bar{Z_B} \bar{U}_{A,B} &= \bar{Z_A}\bar{Z_B} \tag{20}
\end{align}

Envisagez de déterminer l'opération de contrôle NON à satisfaire. Les nombres de 7 bits contenus dans le bloc de code A sont $ A_ {1}, A_ {2}, A_ {3}, A_ {4}, A_ {5}, A_ {6}, A_ {7} $ Ensuite, les nombres de 7 bits contenus dans le bloc de code B sont $ B_ {1}, B_ {2}, B_ {3}, B_ {4}, B_ {5}, B_ {6}, B_ { Disons 7} $, contrôlons le $ i $ ème bit, et écrivons un opérateur de contrôle NOT simple qui cible le $ j $ ème bit comme $ U_ {i, j} $. Alors, $ \ bar {U} _ {A, B} $ qui satisfait l'équation (18) devient

\bar{U}_{A,B} = U_{A_1,B_1} U_{A_2,B_2} U_{A_3,B_3} U_{A_4,B_4} U_{A_5,B_5} U_{A_6,B_6} U_{A_7,B_7}  \tag{21}

Tu peux voir ça. C'est facile à voir. La première équation de l'équation (20) est

\begin{align}
\bar{U}_{A,B} \bar{X_A} \bar{U}_{A,B} &= (U_{A_1,B_1} \cdots U_{A_7,B_7}) (X_{A_1} \cdots X_{A_7}) (U_{A_1,B_1} \cdots U_{A_7,B_7}) \\
&= (U_{A_1,B_1} X_{A_1} U_{A_1,B_1}) \cdots (U_{A_7,B_7} X_{A_7} U_{A_7,B_7}) \\
&= (X_{A_1} X_{B_1}) \cdots (X_{A_7} X_{B_7}) \\
&= (X_{A_1} \cdots X_{A_7}) (X_{B_1} \cdots X_{B_7}) = \bar{X_A} \bar{X_B} \tag{22}
\end{align}

Par conséquent, l'équation (21) est correcte. Vous pouvez voir les deuxième, troisième et quatrième de la même manière. J'étais un peu décontracté, mais à la fin c'est devenu une forme très simple. Si vous écrivez dans le schéma de circuit,

           A1 --*--------------------
[block A]  A2 --|--*-----------------
           A3 --|--|--*--------------
           A4 --|--|--|--*-----------
           A5 --|--|--|--|--*--------
           A6 --|--|--|--|--|--*-----
           A7 --|--|--|--|--|--|--*--
                |  |  |  |  |  |  |
           B1 --X--|--|--|--|--|--|--
[block B]  B2 -----X--|--|--|--|--|--
           B3 --------X--|--|--|--|--
           B4 -----------X--|--|--|--
           B5 --------------X--|--|--
           B6 -----------------X--|--
           B7 --------------------X--

C'est une belle forme, ce qui signifie qu'une commande à tolérance de panne NON a été réalisée. Comme vous pouvez le voir, le bruit d'inversion de bits généré dans le bloc de code A se propage au bloc de code B. Cependant, c'est correct car il ne se propage pas dans le même bloc. Le bruit d'inversion de phase généré dans le bloc de code B se propage également au bloc de code A, mais cela ne se propage pas non plus au même bloc, donc c'est correct (les erreurs peuvent être corrigées dans chaque bloc).

Porte de décalage de phase: T

Ceci termine la porte de Clifford. Une autre porte de déphasage, $ T $ gate, est nécessaire pour rendre le calcul quantique universel. La porte $ T $ est

T =
\begin{pmatrix}
1 & 0\\
0 & e^{i\pi /4}
\end{pmatrix}  \tag{23}

Puisqu'il est défini par, entrez l'état de signe $ \ ket {\ psi} = a \ ket {0_L} + b \ ket {1_L} $ et $ \ ket {\ psi ^ {\ prime}} = a \ ket Ce serait bien si une opération qui renvoie {0_L} + be ^ {i \ pi / 4} \ ket {1_L} $ pouvait être configurée en tolérance aux pannes. Mais ce n'est pas si simple. C'est une manière intelligente [^ 5] qui est un peu déroutante, alors je vais d'abord vous donner la réponse. Le schéma de circuit est

[^ 5]: [Practice 10.65] et "Practice 10.66" de Neilsen, Chan décrit comment dériver ce circuit. Quand j'essaye cet exercice, je vois! Ce sera comme ça. En outre, la "pratique 10.68" décrit comment configurer la porte de Toffoli comme une porte à tolérance de panne d'une manière similaire.

               |C>
                v
|0L>  --/--H--T----*----SX-- T|psi>
                   |    |
|psi> --/----------X----M

est. Que signifie le fait que le premier bloc de code contienne le $ T $ que nous allons définir? Vous avez peut-être pensé. Pensez aux premières portes Adamal et $ T $ dans ce premier bloc de code comme représentant une action qui crache un état similaire à ce calcul. Dans la figure, j'ai écrit $ \ ket {C} $,

\ket{C} = \frac{1}{\sqrt{2}} (\ket{0_L} + e^{i\pi /4} \ket{1_L})  \tag{24}

Ce sera. J'expliquerai comment créer cet état plus tard, mais j'expliquerai l'opération suivante en supposant qu'un tel état est créé. Tout d'abord, appliquez le contrôle NON. Il s'agit de la commande tolérante aux pannes que vous venez de configurer. Un contrôle tolérant aux pannes NOT peut être traité comme si la base était une base logique dans la formule mathématique, donc tout comme un contrôle NOT,

\ket{0_L} \bra{0_L} \otimes I + \ket{1_L} \bra{1_L} \otimes \bar{X}  \tag{25}

Peut être écrit. Par conséquent, l'effet de CNOT sur $ \ ket {C} \ ket {\ psi} $ est

\begin{align}
\ket{C}\ket{\psi} &\rightarrow \frac{1}{\sqrt{2}} (\ket{0_L} \bra{0_L} \otimes I + \ket{1_L} \bra{1_L} \otimes \bar{X}) \ket{C}\ket{\psi} \\
&= \frac{1}{2} (\ket{0_L} \bra{0_L} \otimes I + \ket{1_L} \bra{1_L} \otimes \bar{X}) (\ket{0_L} + e^{i\pi /4} \ket{1_L}) (a\ket{0_L} + b\ket{1_L}) \\
&= \frac{1}{2} (\ket{0_L} (a\ket{0_L}+b\ket{1_L}) + e^{i\pi /4} \ket{1_L} (a\ket{1_L}+b\ket{0_L})) \\
&= \frac{1}{2} ((a\ket{0_L}+b e^{i\pi /4} \ket{1_L}) \ket{0_L} + (b\ket{0_L}+a e^{i\pi /4} \ket{1_L}) \ket{1_L}) \tag{26}
\end{align}

Ce sera. Si le deuxième bloc de code est mesuré et que la valeur mesurée est $ 1 (\ ket {0_L}) $, rien n'est fait, donc la sortie du premier bloc de code est

\ket{\psi^{\prime}} = a\ket{0_L}+b e^{i\pi /4} \ket{1_L} = \bar{T} \ket{\psi}  \tag{27}

Ce sera. Si la valeur mesurée est $ -1 (\ ket {1_L}) $, $ SX $ est calculé, donc l'état de l'équation (27) multiplié par la phase globale est sorti comme premier état de code. ..

Eh bien, il y avait une explication sur la façon de cracher l'état comme l'équation (24). Compte tenu du format du stabilisateur, la conversion de $ \ ket {0_L} $ en $ TH \ ket {0_L} $ est $ \ bar {Z} \ rightarrow \ bar {T} \ bar {H} \ bar {Z} \ bar Il peut être exprimé comme {H} \ bar {T} ^ {\ dagger} $, et peut être exprimé comme $ \ bar {T} \ bar {H} \ bar {Z} \ bar {H} \ bar {T} ^ {\ dagger } $ Est

\begin{align}
\bar{T}\bar{H}\bar{Z}\bar{H}\bar{T}^{\dagger} &= \bar{T}\bar{X}\bar{T}^{\dagger}  \\
&=
\begin{pmatrix}
1 & 0\\
0 & e^{i\pi /4}
\end{pmatrix}
\begin{pmatrix}
0 & 1\\
1 & 0
\end{pmatrix}
\begin{pmatrix}
1 & 0\\
0 & e^{-i\pi /4}
\end{pmatrix} \\
&= e^{-i\pi /4} \bar{S} \bar{X}  \tag{28}
\end{align}

Il peut être réécrit comme. Par conséquent, l'état $ \ ket {C} $ est un état unique pour la valeur unique $ + 1 $ de l'opérateur $ e ^ {-i \ pi / 4} \ bar {S} \ bar {X} $. Cela signifie que $ e ^ {-i \ pi / 4} \ bar {S} \ bar {X} $ est mesuré indirectement, et si la valeur mesurée $ + 1 $ est obtenue, c'est $ \ ket {C} $. Ce sera aussi bien. Si la valeur mesurée est de -1 $, appliquez $ \ bar {Z} $. Ensuite, il passe à l'état de valeur propre $ + 1 $ [^ 6].

[^ 6]: $ \ bar {Z} $ est contre-convertible en $ e ^ {-i \ pi / 4} \ bar {S} \ bar {X} $, donc $ \ bar {Z} \ frac { 1} {2} (Ie ^ {-i \ pi / 4} \ bar {S} \ bar {X}) \ ket {0_L} = \ frac {1} {2} (I + e ^ {-i \ Il devient pi / 4} \ bar {S} \ bar {X}) \ ket {0_L} $, et la valeur unique peut être inversée.

Il y a une mise en garde ici. J'ai dit que $ e ^ {-i \ pi / 4} \ bar {S} \ bar {X} $ est mesuré indirectement, mais un peu d'ingéniosité est nécessaire. Schématiquement

|0>  -----H--*--*----*-----------H-- M
             |  |    |
|0L> --/-----X--S--exp(-i pi/4)-----

Cependant, le problème est la porte contrôlée $ e ^ {-i \ pi / 4} I $. c'est,

|0>  ----*-----------    ---T+--
         |             = 
|0L> --exp(-i pi/4)--    -------

Utilisation de l'équation

|0>  -----H--*--*--T+-H-- M
             |  |
|0L> --/-----X--S--------

Il est bon de le transformer en forme de. La porte $ T $ dans cette figure est juste une porte $ T $.

Nous avons donc maintenant une porte $ T $ pour l'état signé. Les portes $ CNOT, S, X $ peuvent toutes être transversales, elles sont donc tolérantes aux pannes dans leur ensemble. Cependant, aucune considération n'a été accordée à la mesure. On peut dire que la porte $ T $, qui est vraiment tolérante aux pannes, ne peut être réalisée que lorsque la partie de mesure est également transformée en tolérance aux pannes.

Parlons donc des mesures de tolérance aux pannes ensuite.

La mesure

La mesure indirecte de l'opérateur $ ABC $ qui travaille sur l'état signé est

|0> --H--*--*--*--H-- M
         |  |  |
    -----A--|--|-----
    --------B--|-----
    -----------C-----

Vous pouvez le faire en faisant (Comme il s'agit d'une prémisse de code Steane, le bloc de code nécessite en fait 7 lignes, mais par souci de simplicité, il est omis à 3 lignes). Cependant, du point de vue de la tolérance aux pannes, c'est une très mauvaise idée. Si les bits auxiliaires sont bruyants, le bruit peut se propager à tous les bits qui composent le bloc de code. Pour éviter cela, nous savons que la configuration suivante doit être utilisée.

|0> --H--*----*----------*--H-- M
    -----X----|--*-------X-----
    -----X----|--|--*----X-----
              |  |  |
    ----------A--|--|----------
    -------------B--|----------
    ----------------C----------

Réglez le bit auxiliaire sur 3 bits

|0> --H--*--
    -----X--
    -----X--

Ce circuit crée le soi-disant état cat $ (\ ket {000} + \ ket {111}) / \ sqrt {2} $. Une mesure indirecte peut être réalisée de cette manière, et même si du bruit se produit dans les bits auxiliaires, le bruit se propage à un seul bit du bloc de code.

C'est bien, mais cela peut être bruyant lors de la création du premier état de chat. Si du bruit se produit dans l'un des 3 bits auxiliaires, le bruit se propage facilement dans le bloc. Que devrais-je faire? Donc, dans un tel cas, si vous créez un état de chat, vous devez vérifier si cela est fait correctement, et si ce n'est pas correct, supprimez cet état et essayez de le créer à nouveau. Plus précisément, le circuit de contrôle de parité est inséré immédiatement après la création de l'état cat.

Contrôle de parité
      |0> --X--X-- M
            |  |
|0> --H--*--*--|--*----------*--H-- M
    -----X-----*--|--*-------X-----
    -----X--------|--|--*----X-----
                  |  |  |
    --------------A--|--|----------
    -----------------A--|----------
    --------------------A----------

C'est comme ça. Par souci de simplicité, je n'ai écrit qu'un seul contrôle de parité, mais comme il doit être vérifié avec toutes les combinaisons de bits, le contrôle de parité des deuxième et troisième bits est également nécessaire. Répétez la création de l'état de chat jusqu'à ce que toute la parité devienne égale.

C'est un peu difficile, mais maintenant c'est tolérant aux fautes! Je voudrais dire, mais il y a un autre problème. Vous devez également considérer que le bruit d'inversion de phase se produira dans les bits auxiliaires ajoutés pour le contrôle de parité. Dans ce cas, il se propage sur deux bits du bloc de 3 bits pour une mesure indirecte. Cela ne peut pas corriger les erreurs. En conséquence, la mesure la plus à droite produira le mauvais résultat. Dans ce cas également, cela ne peut pas être aidé, alors répétez la mesure trois fois pour obtenir un vote majoritaire. Ensuite, le taux d'erreur peut être réduit à $ O (p ^ 2) $ (en supposant que la probabilité d'occurrence du bruit est $ p $).

Vous avez maintenant configuré une mesure tolérante aux erreurs. La mesure n'est pas seulement nécessaire pour acquérir le résultat du calcul, mais aussi pour la mesure du syndrome pour la correction d'erreur et la création de porte $ T $ expliquée précédemment, ainsi que pour l'état initial décrit ci-après. C'est ce qui devient.

Création de l'état initial

Alors, parlons de la façon de configurer la création de l'état initial en tolérance aux pannes. Dernière fois, Dernière fois État initial du code à 5 bits quantiques (base logique Nous avons décrit en détail comment créer l'état $ \ ket {0_L} $). Il suffit de le remplacer par le code Steane et de remplacer la partie de mesure indirecte par la mesure tolérante aux pannes qui vient d'être décrite.

Les six sources du code Steane et de l'opérateur logique $ Z $ ont été présentées précédemment. Pour créer l'état initial, ces 7 opérateurs sont mesurés dans l'ordre et projetés sur l'espace propre avec la valeur propre de $ + 1 $ l'un après l'autre, mais ils sont projetés sur l'espace propre avec la valeur propre de $ -1 $. Dans ce cas, il aurait été préférable d'appliquer un opérateur anti-commutable avec la source concernée et compatible avec d'autres sources. Dans le cas du code Steane, il existe les 7 opérateurs suivants [^ 7]. Je le posterai ici car il sera nécessaire lors de la vérification de l'opération plus tard.

[^ 7]: Je pense qu'il y a d'autres options, mais j'ai énuméré celles que j'ai proposées à titre d'exemple.

opérateur
g_{1}^{\prime} Z \space Z \space Z \space Z \space I \space I \space I
g_{2}^{\prime} Z \space Z \space I \space I \space Z \space Z \space I
g_{3}^{\prime} I \space I \space Z \space I \space Z \space I \space Z
g_{4}^{\prime} X \space X \space X \space X \space I \space I \space I
g_{5}^{\prime} X \space X \space I \space I \space X \space X \space I
g_{6}^{\prime} I \space I \space X \space I \space X \space I \space X
g_{7}^{\prime} X \space X \space X \space X \space X \space X \space X

Vous savez maintenant comment configurer tout le processus requis pour le calcul quantique (création de l'état initial, calcul de porte, mesure) en tolérance aux pannes.

Maintenant, la question suivante est de savoir à quel point le taux d'erreur du calcul quantique peut être faible. En supposant que la probabilité d'erreur dans chaque composant du système est de $ p $, le taux d'erreur du résultat du calcul peut être réduit à $ O (p ^ 2) $ au plus, mais à quel point il peut être réduit. Est-ce? En fait, si $ p $ est en dessous d'un certain seuil, il existe un moyen de le rendre aussi petit que vous le souhaitez. Je vais l'expliquer ci-dessous.

Code de concaténation et théorème de seuil

Les composants qui composent le système informatique quantique comprennent un bit quantique, un dispositif de contrôle qui le contrôle, un dispositif de mesure pour mesurer l'état quantique, etc., et chacun d'eux reçoit un dysfonctionnement ou un bruit du monde extérieur, et est prédéterminé. Il y a une certaine probabilité que cela ne fonctionnera pas. Supposons très simplement que la probabilité moyenne est de $ p $. Comme expliqué dans les sections précédentes, au plus une erreur par bloc de code peut être corrigée. Le problème est lorsque deux erreurs se produisent en même temps et se propagent pour obtenir deux erreurs dans un bloc de code particulier. Sa probabilité est proportionnelle à $ p ^ 2 $ et est $ cp ^ 2 $. Ce coefficient de proportionnalité $ c $ est le nombre dans le cas de "causer deux erreurs dans un bloc de code spécifique". Neilsen, Chan dit $ c \ approx 10 ^ {4} $ comme une estimation très approximative utilisant un simple circuit quantique comme exemple. La valeur est publiée.

Afin de réduire ce taux d'erreur, envisagez de coder davantage chaque bit quantique qui constitue le bloc de code et le bloc auxiliaire pour la correction d'erreur. Puisque 1 bit du système d'origine était 7 fois + $ \ alpha $ par le code Steane, il est encore 7 fois + $ \ alpha $. L'échelle du système sera grande, mais grâce à cela, le taux d'erreur sera $ c (cp ^ 2) ^ 2 = c ^ {3} p ^ {4} $. Encore une fois, si chaque bit est encodé avec un code Steane, l'échelle du système sera 7 fois supérieure à + $ \ alpha $, et le taux d'erreur sera $ c (c (cp ^ 2) ^ 2) ^ 2 = c ^ {7} p ^. Ce sera {8} $. Si cette opération est répétée $ k $ fois, l'échelle système (nombre de bits requis) sera $ d ^ k $ lorsque l'échelle système d'origine est $ d $, et le taux d'erreur sera $ (cp) ^ {2. Ce sera ^ k} / c $. La construction hiérarchique du codage de cette manière est appelée un "code concaténé".

Supposons que le système informatique quantique auquel vous pensez ait à l'origine des portes $ p (n) $. Supposons que $ n $ représente l'ampleur d'un problème et que $ p (n) $ est une fonction polymorphe pour $ n $. Si le taux d'erreur que vous souhaitez atteindre au final est $ \ epsilon $,

\frac{(cp)^{2^k}}{c} \leq \frac{\epsilon}{p(n)}  \tag{29}

La relation doit être établie. Comme vous pouvez le voir, si $ p $ atteint un certain seuil $ p_ {th} <1 / c $, vous pouvez réduire le taux d'erreur autant que vous le souhaitez en augmentant suffisamment la valeur de $ k $. Comme estimation approximative, c'était $ c \ approx 10 ^ {4} $, donc $ p_ {th} \ approx 10 ^ {-4} = 0.01 % $.

Quelle est donc la taille du système (nombre de bits) $ d ^ k $ nécessaire pour atteindre le taux d'erreur $ \ epsilon $? Elle peut être trouvée en remplaçant l'inégalité dans l'équation (27) par une approximation et en la transformant comme suit.

d^k \approx (\frac{\log(p(n)/c\epsilon)}{\log(1/pc)})^{\log d} = O(poly(\log p(n)/\epsilon))  \tag{30}

Le nombre de portes incluses est

O(poly(\log p(n)/\epsilon) p(n))  \tag{31} 

Peut être estimé. Autrement dit, un circuit quantique contenant des portes $ p (n) $ dépend du matériel dont la probabilité d'erreur de composant est au plus $ p $.

O(poly(\log p(n)/\epsilon) p(n))  \tag{32} 

Un taux d'erreur de $ \ epsilon $ peut être obtenu en utilisant plusieurs portes. Cependant, $ p $ doit être inférieur à un certain seuil. C'est ce qu'on appelle le "théorème de seuil".

Contrôle de fonctionnement

Maintenant que je comprends la théorie, je voudrais prendre un exemple très simple de calcul quantique tolérant aux pannes et vérifier le fonctionnement avec le simulateur de calcul quantique qlazy. J'ai expliqué ci-dessus comment rendre la porte $ T $ tolérante aux pannes, mais j'ai trouvé que c'était un peu délicat, alors voyons si cela fonctionne vraiment. Même si la porte $ T $ est appliquée à l'état $ \ ket {0_L} $, elle reste $ \ ket {0_L} $ et ce n'est pas du tout intéressant, alors appliquez Adamar d'avant en arrière et $ \ bar {H} \ bar { Effectuez l'opération T} \ bar {H} \ ket {0_L} $ et enfin mesurez avec la base $ \ bar {Z} $. Pour le moment, toutes les opérations et mesures du portail sont configurées comme tolérantes aux pannes. Cependant, j'ai omis le processus d'ajout de bruit et de correction de l'erreur (depuis que je l'ai fait la dernière fois). De plus, nous avons omis le contrôle de parité pour vérifier si l'état du chat est correct et la méthode de mesure plusieurs fois et de prendre une décision à la majorité. Quoi qu'il en soit, cette fois, je me suis concentré uniquement sur la confirmation que l'arithmétique et la mesure de l'état du code ont été correctement réalisées dans la configuration tolérante aux pannes.

la mise en oeuvre

Regardons maintenant tout le code Python.

from qlazypy import QState

def logical_zero():

    anc = [0,1,2,3,4,5,6]     # registers for ancila
    cod = [7,8,9,10,11,12,13] # registers for steane code
    qs_total = QState(14)

    # g1
    qs_total.h(anc[0])
    [qs_total.cx(anc[0], anc[i]) for i in range(1,4)]
    qs_total.cx(anc[0], cod[3]).cx(anc[1], cod[4]).cx(anc[2], cod[5]).cx(anc[3], cod[6])
    [qs_total.cx(anc[0], anc[i]) for i in range(1,4)]
    qs_total.h(anc[0])
    mval = qs_total.m(qid=[anc[0]]).last
    if mval == '1': qs_total.z(cod[0]).z(cod[1]).z(cod[2]).z(cod[3])
    qs_total.reset(qid=anc)

    # g2
    qs_total.h(anc[0])
    [qs_total.cx(anc[0], anc[i]) for i in range(1,4)]
    qs_total.cx(anc[0], cod[1]).cx(anc[1], cod[2]).cx(anc[2], cod[5]).cx(anc[3], cod[6])
    [qs_total.cx(anc[0], anc[i]) for i in range(1,4)]
    qs_total.h(anc[0])
    mval = qs_total.m(qid=[anc[0]]).last
    if mval == '1': qs_total.z(cod[0]).z(cod[1]).z(cod[4]).z(cod[5])
    qs_total.reset(qid=anc)

    # g3
    qs_total.h(anc[0])
    [qs_total.cx(anc[0], anc[i]) for i in range(1,4)]
    qs_total.cx(anc[0], cod[0]).cx(anc[1], cod[2]).cx(anc[2], cod[4]).cx(anc[3], cod[6])
    [qs_total.cx(anc[0], anc[i]) for i in range(1,4)]
    qs_total.h(anc[0])
    mval = qs_total.m(qid=[anc[0]]).last
    if mval == '1': qs_total.z(cod[2]).z(cod[4]).z(cod[6])
    qs_total.reset(qid=anc)

    # g4
    qs_total.h(anc[0])
    [qs_total.cx(anc[0], anc[i]) for i in range(1,4)]
    qs_total.cz(anc[0], cod[3]).cz(anc[1], cod[4]).cz(anc[2], cod[5]).cz(anc[3], cod[6])
    [qs_total.cx(anc[0], anc[i]) for i in range(1,4)]
    qs_total.h(anc[0])
    mval = qs_total.m(qid=[anc[0]]).last
    if mval == '1': qs_total.x(cod[0]).x(cod[1]).x(cod[2]).x(cod[3])
    qs_total.reset(qid=anc)
    
    # g5
    qs_total.h(anc[0])
    [qs_total.cx(anc[0], anc[i]) for i in range(1,4)]
    qs_total.cz(anc[0], cod[1]).cz(anc[1], cod[2]).cz(anc[2], cod[5]).cz(anc[3], cod[6])
    [qs_total.cx(anc[0], anc[i]) for i in range(1,4)]
    qs_total.h(anc[0])
    mval = qs_total.m(qid=[anc[0]]).last
    if mval == '1': qs_total.x(cod[0]).x(cod[1]).x(cod[4]).x(cod[5])
    qs_total.reset(qid=anc)

    # g6
    qs_total.h(anc[0])
    [qs_total.cx(anc[0], anc[i]) for i in range(1,4)]
    qs_total.cz(anc[0], cod[0]).cz(anc[1], cod[2]).cz(anc[2], cod[4]).cz(anc[3], cod[6])
    [qs_total.cx(anc[0], anc[i]) for i in range(1,4)]
    qs_total.h(anc[0])
    mval = qs_total.m(qid=[anc[0]]).last
    if mval == '1': qs_total.x(cod[2]).x(cod[4]).x(cod[6])
    qs_total.reset(qid=anc)

    # g7
    qs_total.h(anc[0])
    [qs_total.cx(anc[0], anc[i]) for i in range(1,7)]
    [qs_total.cz(anc[i], cod[i]) for i in range(7)]
    [qs_total.cx(anc[0], anc[i]) for i in range(1,7)]
    qs_total.h(anc[0])
    mval = qs_total.m(qid=[anc[0]]).last
    if mval == '1': [qs_total.x(q) for q in cod]
    qs_total.reset(qid=anc)

    qs = qs_total.partial(qid=cod)
    qs_total.free()

    return qs

def faulttolerant_t(qs_in):

    A = [0,1,2,3,4,5,6]         # registers for ancila
    B = [7,8,9,10,11,12,13]     # registers for output quantum state
    C = [14,15,16,17,18,19,20]  # registers for input quantum state
    qs_A = QState(7)
    qs_B = logical_zero()
    qs_AB = qs_A.tenspro(qs_B)
    qs_ABC = qs_AB.tenspro(qs_in)

    # -H-T-
    qs_ABC.h(A[0])
    [qs_ABC.cx(A[0], A[i]) for i in range(1,7)]
    # [qs_ABC.cx(A[i],B[i]).cs(A[i],B[i]).cz(A[i],B[i]).t_dg(A[i]) for i in range(7)]
    [qs_ABC.cx(A[i],B[i]).cs(A[i],B[i]).cz(A[i],B[i]) for i in range(7)]

    [qs_ABC.cx(A[0], A[i]) for i in range(1,7)]
    # qs_ABC.h(A[0])
    qs_ABC.t_dg(A[0]).h(A[0])
    mval = qs_ABC.m(qid=[A[0]]).last
    if mval == '1': [qs_ABC.z(q) for q in B]
    qs_ABC.reset(qid=A)

    # -CNOT-
    [qs_ABC.cx(B[i], C[i]) for i in range(7)]
    
    # -M-, -SX-
    qs_ABC.h(A[0])
    [qs_ABC.cx(A[0], A[i]) for i in range(1,7)]
    [qs_ABC.cz(A[i],C[i]) for i in range(7)]
    [qs_ABC.cx(A[0], A[i]) for i in range(1,7)]
    qs_ABC.h(A[0])
    mval = qs_ABC.m(qid=[A[0]]).last
    if mval == '1': [qs_ABC.x(q).s(q).z(q) for q in B]

    qs_out = qs_ABC.partial(qid=B)
    QState.free_all(qs_A, qs_B, qs_AB, qs_ABC)

    return qs_out

def faulttolerant_m(qs_in):

    anc = [0,1,2,3,4,5,6]      # ancila
    cod = [7,8,9,10,11,12,13]  # steane code
    qs_anc = QState(7)
    qs_total = qs_anc.tenspro(qs_in)

    qs_total.h(anc[0])
    [qs_total.cx(anc[0], anc[i]) for i in range(1,7)]
    [qs_total.cz(anc[i], cod[i]) for i in range(7)]
    [qs_total.cx(anc[0], anc[i]) for i in range(1,7)]
    qs_total.h(anc[0])
    md = qs_total.m(qid=[0], shots=10000)
    QState.free_all(qs_anc, qs_total)

    return md

if __name__ == '__main__':

    qs = QState(1).h(0).t(0).h(0)    # not fault-tolerant -HTH-
    qs.show()
    
    qs_ini = logical_zero()          # make initial state (logical zero)
    [qs_ini.h(i) for i in range(7)]  # operate fault-tolerant H
    qs_fin = faulttolerant_t(qs_ini) # operate fault-tlerant T
    [qs_fin.h(i) for i in range(7)]  # operate fault-tolerant H
    md = faulttolerant_m(qs_fin)     # execute fault-tolerant measurement
    print(md.frequency)

    QState.free_all(qs, qs_ini, qs_fin)

Je vais expliquer brièvement ce que vous faites. Tout d'abord, jetez un œil à la section de traitement principale.

qs_ini = logical_zero()          # make initial state (logical zero)

Donc, nous créons l'état de base logique $ \ ket {0_L} $ du code Steane. Les détails sont dans la fonction logic_zero, mais cela peut être très long et déroutant. Mais les bases sont simples,

# g1
qs_total.h(anc[0])
[qs_total.cx(anc[0], anc[i]) for i in range(1,4)]
qs_total.cx(anc[0], cod[3]).cx(anc[1], cod[4]).cx(anc[2], cod[5]).cx(anc[3], cod[6])
[qs_total.cx(anc[0], anc[i]) for i in range(1,4)]
qs_total.h(anc[0])
mval = qs_total.m(qid=[anc[0]]).last
if mval == '1': qs_total.z(cod[0]).z(cod[1]).z(cod[2]).z(cod[3])
qs_total.reset(qid=anc)

C'est une répétition du code comme. Mesurer indirectement la source avec le bit auxiliaire à l'état cat. Si le résultat de la mesure est 1 (c'est-à-dire $ \ ket {1_L} $), l'opérateur qui est anti-commutable avec la source est appliqué. Lorsque les sept opérateurs sont terminés, l'état est retourné (à l'exception des bits auxiliaires). Ici, la dernière méthode pour obtenir la valeur mesurée est d'obtenir la chaîne binaire (ajoutée dans la v0.0.41). prochain,

[qs_ini.h(i) for i in range(7)]  # operate fault-tolerant H

Donc, j'applique la tolérance aux pannes Adamar. C'est un type transversal, donc c'est facile.

qs_fin = faulttolerant_t(qs_ini) # operate fault-tlerant T

Et j'utilise une porte $ T $ tolérante aux pannes. Jetons un œil au contenu de la fonction faulttolerant_t. Le premier bloc de code expliqué ci-dessus est nommé B, le deuxième bloc de code est nommé C et le bloc auxiliaire requis pour la mesure est nommé A. Chacun se compose de 7 bits. J'espère que vous pouvez le voir sur place.

# -H-T-
qs_ABC.h(A[0])
[qs_ABC.cx(A[0], A[i]) for i in range(1,7)]
[qs_ABC.cx(A[i],B[i]).cs(A[i],B[i]).cz(A[i],B[i]).t_dg(A[i]) for i in range(7)]
[qs_ABC.cx(A[0], A[i]) for i in range(1,7)]
qs_ABC.h(A[0])
mval = qs_ABC.m(qid=[A[0]]).last
if mval == '1': [qs_ABC.z(q) for q in B]
qs_ABC.reset(qid=A)

Crée le même état de signe que l'application de $ H $ et $ T $. J'ai mis le bit auxiliaire à l'état cat et mesure l'opérateur $ e ^ {-i \ pi / 4} SX $, mais comme le type transversal de $ S $ était $ ZS $, je contrôle $ ZSX $. va le faire. De plus, puisque la phase $ e ^ {-i \ pi / 4} $ était égale à la porte $ T $ côté contrôle, je me souviens d'inclure ce calcul.

# -CNOT-
[qs_ABC.cx(B[i], C[i]) for i in range(7)]

Alors, faites un CNOT transversal,

# -M-, -SX-
qs_ABC.h(A[0])
[qs_ABC.cx(A[0], A[i]) for i in range(1,7)]
[qs_ABC.cz(A[i],C[i]) for i in range(7)]
[qs_ABC.cx(A[0], A[i]) for i in range(1,7)]
qs_ABC.h(A[0])
mval = qs_ABC.m(qid=[A[0]]).last
if mval == '1': [qs_ABC.x(q).s(q).z(q) for q in B]

Si le bloc de code C est mesuré et que le résultat de la mesure est 1, $ SX $ est appliqué au bloc de code A. Encore une fois, rappelez-vous que le type transversal de $ S $ était $ ZS $. Le résultat doit être dans le bloc de code B,

qs_out = qs_ABC.partial(qid=B)

Ainsi, le système partiel correspondant au bloc de code B est extrait par la méthode partielle. Je reviendrai ceci.

Revenez à la section de traitement principale.

Pour le résultat de la porte $ T $

[qs_fin.h(i) for i in range(7)]  # operate fault-tolerant H

Donc, calculez à nouveau Adamar comme tolérant aux pannes, et enfin,

md = faulttolerant_m(qs_fin)     # execute fault-tolerant measurement
print(md.frequency)

Ensuite, effectuez la mesure. Voir le contenu de la fonction faulttolerant_m pour plus de détails. Il s'agit simplement d'une mesure indirecte avec le bit auxiliaire à l'état cat. Le résultat de la mesure est acquis en tant que variable md (une instance de la classe MData), et les données de fréquence sont obtenues au format Counter par la méthode de fréquence (ajoutée dans la v0.0.41). c'est tout.

résultat

Le résultat de l'exécution est indiqué ci-dessous.

c[0] = +0.9239-0.0000*i : 0.8536 |++++++++++
c[1] = +0.0000-0.3827*i : 0.1464 |++
Counter({'0': 8524, '1': 1476})

Les deux premières lignes sont le résultat d'un -H-T-H- normal qui n'est pas tolérant aux pannes. Voilà la réponse. Cela signifie que les probabilités pour les états $ \ ket {0_L} $ et $ \ ket {1_L} $ sont respectivement de 0,8536 et 0,1464. Le compteur sur la 3ème ligne est le résultat de l'exécution du tolérant aux pannes -H-T-H- et de la simulation 10000 fois. Je pense que cela correspond à peu près à la probabilité de réponse (pensez!).

en conclusion

J'ai trouvé que le calcul quantique tolérant aux pannes est une technique très difficile à réaliser en utilisant pleinement diverses techniques. Afin de créer un ordinateur quantique vraiment pratique, ce type d'accumulation régulière est important, n'est-ce pas? Le théorème du seuil était une réalisation théorique extrêmement importante qui pourrait être considérée comme une réalisation de soutien qui garantit que l'effort sera sûrement récompensé. Même ainsi, le taux d'erreur de 10 $ ^ {-4} = 0,01 % $ est une exigence stricte. En supposant un code de correction d'erreur tel qu'un code de stabilisateur et un code de concaténation, ce niveau de précision est absolument nécessaire. Cependant, il semble que ce seuil puisse être relevé en utilisant une méthode de codage différente. La prochaine fois, j'aimerais étudier une de ces méthodes de codage, le "code topologique (code de surface)".

c'est tout

Recommended Posts

Bases de la théorie de l'information quantique: calcul quantique tolérant aux pannes
Bases de la théorie de l'information quantique: Entropie (2)
Bases de la théorie de l'information quantique: compression de données (1)
Bases de la théorie de l'information quantique: limites d'Horebaud
Bases de la théorie de l'information quantique: distance de trace
Bases de la théorie de l'information quantique: tomographie d'état quantique
Bases de la théorie de l'information quantique: compression de données (2)
Bases de la théorie de l'information quantique: codes de surface topologique
Bases de la théorie de l'information quantique: correction d'erreur quantique (code Shor)
Bases de la théorie de l'information quantique: correction d'erreur quantique (code CSS)
Bases de la théorie de l'information quantique: correction d'erreur quantique (code du stabilisateur: 4)
Bases de la théorie de l'information quantique: correction d'erreur quantique (code linéaire classique)
Bases de la théorie de l'information quantique: calcul quantique universel par code de surface (1)
Lire "Principes de base du recuit quantique" Jour 5
Principes de base de Tableau (visualisation à l'aide d'informations géographiques)
Les bases de Python ①
Bases de python ①