[PYTHON] Grundlagen der Quanteninformationstheorie: Fehlertolerante Quantenberechnung

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

Einführung

Bis zu vorherigen konnte ich den "Fehlerkorrekturcode" verstehen. Damit kann der Fehler korrigiert und das Berechnungsergebnis korrekt erhalten werden, selbst wenn dem Quantencomputer etwas Rauschen hinzugefügt wird! Ich würde gerne sagen (zumindest theoretisch!), Aber es ist überhaupt nicht! Ich werde von nun an darüber sprechen. Rauschen kann überall im Quantencomputerprozess auftreten, und für jeden von ihnen ist eine spezielle Behandlung erforderlich. Man kann sagen, dass eine fehlertolerante Quantenberechnung, die fehlertolerant ist und auch bei Fehlern korrekt funktioniert, erst nach deren Implementierung realisiert wurde.

Lassen Sie mich zunächst sagen, was ich in den folgenden Abschnitten zu erklären versuche. Zunächst werden wir in der "theoretischen Erklärung", nachdem wir erklärt haben, was es bedeutet, fehlertolerant zu sein, konkret fehlertolerante Quantentore und Methoden zur Realisierung der Messung und der Erzeugung des Anfangszustands einführen und Codes und Schwellenwertsätze verbinden. Dieser Abschnitt erklärt. In "Operation check" nehmen wir ein sehr einfaches Beispiel für eine fehlertolerante Quantenberechnung und überprüfen ihre Funktionsweise mit dem Quantenberechnungssimulator qlazy.

Die folgenden Dokumente wurden als Referenz verwendet.

  1. Neilsen, Chan "Quantencomputer und Quantenkommunikation (3)" Ohm (2005)

Erklärung der Theorie

Definition der Fehlertoleranz

Der Fehlerkorrekturcode entspricht dem Rauschen, das beim Speichern und Übertragen des Quantenzustands erzeugt wird. Da die eigentliche Quantenberechnung aus einer Reihe von Prozessen wie "Anfangszustandserstellung", "Gate-Operation" und "Messung" besteht, reicht der Fehlerkorrekturcode allein nicht aus. Wie führen Sie beispielsweise eine Gate-Operation durch? Sollten wir den codierten Zustand nicht einfach einmal dekodieren, die Gate-Operation ausführen und ihn dann sofort erneut codieren? Sie könnten denken, aber die Idee ist nicht gut. Während des Decodierungs- und Codierungsprozesses und der Gate-Operationen kann Rauschen eingemischt werden. Daher ist es besser, die Gate-Operation im codierten Zustand auszuführen, aber es reicht nicht aus, das Gate so zu konfigurieren, dass es nicht decodiert werden muss. Es muss so konfiguriert sein, dass sich irgendwo erzeugtes Rauschen nicht ausbreitet und vermehrt. Zum Beispiel ist das Steuer-NICHT-Gatter (CNOT-Gatter) ein Gatter, das in jeder Situation sehr nützlich ist, aber wenn $ U_ {1,2} $ die Steuer-NICHT-Operation ist, ist $ U_ {1,2} X_ {1} = X_ {1} Da X_ {2} U_ {1,2} $ gilt, breitet sich das auf der Steuerseite des Eingangs erzeugte Bitinversionsrauschen sowohl auf die Steuerseite als auch auf die Zielseite des Ausgangs aus. Andererseits gilt $ U_ {1,2} Z_ {2} = Z_ {1} Z_ {2} U_ {1,2} $, so dass das auf der Eingangszielseite erzeugte Phaseninversionsrauschen die Ausgangssteuerseite und das Ziel ist. Zur Seite ausbreiten. Wenn Sie es in ein Diagramm schreiben, wird es wie folgt weitergegeben.

[X]Propagiert zu Kontrolle / Ziel>

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


<Phasenumkehr auf der Zielseite[Z]Propagiert zu Kontrolle / Ziel>

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

Es wäre sehr schlecht, wenn es einen solchen Teil in der Gate-Operation für den codierten Zustand gäbe. Eine Fehlerkorrektur ist möglich, wenn sie nur einmal in einem Codeblock auftritt. Bei der obigen Konfiguration steigt jedoch ein Rauschen auf zwei, was eine Korrektur unmöglich macht. Daher muss es so konfiguriert werden, dass dies verhindert wird. Darüber hinaus kann nicht nur die Gate-Berechnung, sondern auch das Fehlerkorrekturverfahren selbst Rauschen erzeugen, so dass diese Maßnahme ebenfalls erforderlich ist. Zusätzlich kann Rauschen in den Erstellungsprozess und den Messprozess des Anfangszustands eingemischt werden.

Und so weiter habe ich allmählich das Gefühl, dass fehlertolerant unmöglich ist. Weil CNOT Rauschen verbreitet. Ist es möglich, CNOT für den Codezustand ohne Verwendung von CNOT zu realisieren? Ist es möglich, Fehler ohne CNOT zu korrigieren? Aber mach dir keine Sorgen. In der Tat bedeutet dies nicht, dass Sie niemals CNOT verwenden sollten. Es ist kein Problem, wenn die Ausbreitung bestimmte Bedingungen erfüllt. Die Bedingung (= Definition der Fehlertoleranz) lautet: "Wenn in dem System, das die Quantenberechnung ausführt, ein Rauschen auftritt, wird in jedem Codeblock höchstens ein Rauschen erzeugt." ". Da ein Rauschen pro Codeblock korrigiert werden kann, ist die Ausbreitung zu demselben Codeblock, in dem das Rauschen aufgetreten ist, nicht gut (da es zwei Rauschen pro Block gibt), sondern zur Ausbreitung zu anderen Blöcken Ist erlaubt (weil ein Geräusch korrigiert werden kann). Wenn das Quantencomputersystem auf diese Weise konfiguriert ist, kann es als fehlertolerant bezeichnet werden.

Leider kann Rauschen an mehreren Stellen gleichzeitig auftreten [^ 1]. Und leider kann die Ausbreitung zu zwei Geräuschen im selben Codeblock führen. In diesem Fall ist das Berechnungsergebnis falsch. Die Wahrscheinlichkeit sollte jedoch auf höchstens $ O (p ^ {2}) $ unterdrückt werden, vorausgesetzt, die Wahrscheinlichkeit, dass an einer Stelle Rauschen auftritt, beträgt $ p $. Dies ist offensichtlich fehlertolerant, da die Wahrscheinlichkeit einer falschen Berechnung $ O (p) $ beträgt und $ O (p ^ {2}) $ ist, wenn keine Aktion für den Fehler ausgeführt wird. Es ist ein Effekt. Mit anderen Worten kann die Tatsache, dass die Berechnungsfehlerrate höchstens $ O (p ^ {2}) $ beträgt, als eines der Merkmale der fehlertoleranten Quantenberechnung angesehen werden.

[^ 1]: "Simultan" bedeutet, dass ein anderes Rauschen erzeugt wird, bevor die Fehlerkorrektur für ein Rauschen ausgeführt wird (glaube ich).

Struktur der fehlertoleranten Quantenberechnung

Schauen wir uns nun an, wie "Gate-Berechnung", "Messung" und "Erstellung des Anfangszustands" als fehlertolerant konfiguriert werden können. Da es am einfachsten ist, mit dem Steane-Code von 7 Quantenbits zu denken, wird in allen folgenden Diskussionen der Steane-Code [^ 2] angenommen.

[^ 2]: Im Fall von 5-Quantenbit-Code ist es ziemlich schwierig, den Gate-Betrieb fehlertolerant zu machen. Es scheint jedoch, dass sowohl $ X $ als auch $ Z $ zu dem Transversaltyp gemacht werden können, der später erklärt wird. Ist es also nicht so schwierig? Ich fühle das, aber ich denke, dass es an einem Ort eine Wand gibt, die ich noch nicht verstanden habe, vielleicht weil ich einen schrecklichen Fehler mache. Es wird meine zukünftige Hausaufgabe sein, über Fehlertoleranz mit 5 Quantenbits nachzudenken.

Torberechnung

Pauligate: X, Y, Z.

Beginnen Sie mit Pauli $ Z $. Die Steane-Codelogik $ Z $ ist mit allen sechs Quellen austauschbar.

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

Kann definiert werden als. Die Quelle ist

Quelle Operator
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

Sie sehen also, dass die Definition von Gleichung (1) gut ist [^ 3].

[^ 3]: Der gleiche Operator wird als $ X_ {1} Z_ {2} X_ {3} $, $ X \ otimes Z \ otimes X $ oder $ XZX $ geschrieben, aber die Substanz ist Es ist das gleiche, also nicht verwirren.

Der von den 7 Operatoren eindeutig bestimmte Stabilisatorzustand, bei dem $ \ bar {Z} $ zu den 6 Generatoren hinzugefügt wird, ist $ \ ket {0_L} $ und $ \ bar {Z} $ ist $ - \ bar { Sei $ \ ket {1_L} $ der Stabilisatorzustand, der beim Wechsel zu Z} $ eindeutig bestimmt wird. Dann

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

Und wenn $ \ bar {Z} $ durch die logische Basis $ \ {\ ket {0_L}, \ ket {1_L} \} $ ausgedrückt wird,

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

Es wird Ihnen bekannt vorkommen. Bisher ist dies eine Überprüfung, um Sie daran zu erinnern, was Sie getan haben, als Sie den Fehlerkorrekturcode verwendet haben. Worauf ich hier achten möchte, ist die Form von Gleichung (1). Wenn in eine Quantenschaltung geschrieben,

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

Es wird sein. Wie Sie sehen können, erfolgt dies in Form einer bitweisen Ausführung einer $ Z $ -Operation, und das Rauschen in einem Bit wirkt sich nicht auf die anderen Bits im Codeblock aus. Die Eigenschaft, die ein codiertes Gate durch eine bitweise Gate-Operation realisieren kann, wird als "Transversalität" bezeichnet, und es kann sofort gesagt werden, dass es sich um eine fehlertolerante Gate-Operation handelt.

Als nächstes kommt Pauli $ X $.

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

Alles was Sie tun müssen, ist $ \ bar {X} $ zu entscheiden, um zu befriedigen. Zum Beispiel

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

Du kannst gehen. Dann

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

Also [^ 4] ist die Matrixdarstellung in der logischen Basis

[^ 4]: $ \ bar {X} \ ket {0_L} = \ bar {X} \ bar {Z} \ ket {0_L} = - \ bar {Z} \ bar {X} \ ket {0_L} $ $ \ Bar {X} \ ket {0_L} $ ist also ein eindeutiger Status für den eindeutigen Wert $ -1 $ von $ \ bar {Z} $. Das heißt, $ \ bar {X} \ ket {0_L} = \ ket {1_L} $. Die Berechnung von $ \ bar {X} $ auf beiden Seiten ergibt $ \ bar {X} \ ket {1_L} = \ ket {0_L} $. Im Detail denke ich, dass die Definition von $ \ bar {X} \ ket {0_L} = e ^ {i \ alpha} \ ket {1_L} $ verwendet werden kann, aber $ \ alpha = 0 $ Ich denke das ist eine Praxis.

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

ist. Wie Sie aus der Form von Gleichung (5) sehen können, handelt es sich auch um einen Transversaltyp. Dies bedeutet, dass ein fehlertolerantes Pauli $ X $ realisiert wurde.

Für 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}

Wenn Sie es als festlegen, passt alles in einen Kreis. Das heißt, $ \ bar {Y} $ ist gegenkonvertierbar in $ \ bar {X} $ und $ \ bar {Z} $, und $ \ bar {Y} $ selbst wird zu Elmeet

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

Die Matrixdarstellung ist also

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

Es wird sein. Da Gleichung (8) ein Transversaltyp ist, bedeutet dies, dass ein fehlertolerantes Pauli $ Y $ realisiert wurde.

Adamal Gate: H.

Basierend auf $ \ bar {X}, \ bar {Y}, \ bar {Z} $ konfigurieren wir das Adamar-Gate für den Vorzeichenstatus als fehlertolerant.

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

Ich muss nur entscheiden, ob $ \ bar {H} $ zufriedenstellend ist

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

Sie können sehen, dass Gleichung (11) erfüllt ist.

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

Wie Sie sehen können, ist $ \ bar {H} \ ket {0_L} $ der Eigenzustand von $ \ bar {X} $ und $ \ bar {H} \ ket {1_L} $ der Eigenzustand von $ \ Eindeutiger Wert von bar {X} $ Der eindeutige Status von $ -1 $. Daher jeder

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

Die Matrixdarstellung kann geschrieben werden als

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

Es wird sein. Wie Sie aus Gleichung (12) sehen können, handelt es sich um einen Transversaltyp. Dies bedeutet, dass ein fehlertolerantes Adamal-Gate realisiert wurde.

Phasenschieber: S.
\bar{S}\bar{X}\bar{S}^{\dagger} = \bar{Y}, \space \bar{S}\bar{Z}\bar{S}^{\dagger} = \bar{Z} \tag{16}

Bestimmen Sie, ob $ \ bar {S} $ erfüllt werden soll.

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

Ich denke für einen Moment, dass ich gehen kann, aber damit gilt Gleichung (16) nicht.

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

Wenn ja, ist es in Ordnung (ich denke, Sie können es leicht überprüfen). Die Matrixdarstellung zur Erfüllung von Gleichung (16) ist

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

(Ich denke, Sie können dies auch leicht überprüfen). Wie Sie aus Gleichung (18) sehen können, handelt es sich um einen Transversaltyp. Dies bedeutet, dass ein fehlertolerantes Phasenverschiebungsgatter realisiert wurde.

Ich glaube nicht, dass ich falsch liege, aber nur für den Fall, wenn ich einen Schaltplan schreibe,

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

ist. In der Industrie ist allgemein bekannt, dass die Reihenfolge der Operatoren in mathematischen Formeln und die Reihenfolge der Operatoren in Schaltplänen umgekehrt sind, wenn Sie sie jedoch versehentlich falsch implementieren (Sie selbst). Ist Schweiß).

Steuerung NICHT Tor: CNOT

Nun ist die Steuerung NICHT Gate in Frage. Ist es möglich, es so zu konfigurieren, dass es sich nicht innerhalb desselben Codeblocks ausbreitet? Wir schreiben $ \ bar {U} _ {A, B} $ als Steuer-NICHT-Operator für den Codezustand, in dem der Codeblock $ A $ als Steuerbit und der Codeblock $ B $ als Zielbit betrachtet wird. In diesem 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}

Erwägen Sie, die zu erfüllende Steuerungs-NICHT-Operation zu bestimmen. Die im Codeblock A enthaltenen 7-Bit-Nummern sind $ A_ {1}, A_ {2}, A_ {3}, A_ {4}, A_ {5}, A_ {6}, A_ {7} $ Dann sind die im Codeblock B enthaltenen 7-Bit-Nummern $ B_ {1}, B_ {2}, B_ {3}, B_ {4}, B_ {5}, B_ {6}, B_ { Sagen wir 7} $, steuern Sie das $ i $ -te Bit und schreiben Sie einen einfachen NOT-Operator, der auf das $ j $ -te Bit als $ U_ {i, j} $ abzielt. Dann wird $ \ bar {U} _ {A, B} $, das Gleichung (18) erfüllt

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

Sie können sehen, dass. Es ist leicht zu sehen. Die erste Gleichung in Gleichung (20) ist

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

Daher ist Gleichung (21) in Ordnung. Sie können den zweiten, dritten und vierten auf dieselbe Weise sehen. Ich war etwas entspannt, aber am Ende wurde es eine sehr einfache Form. Wenn Sie in den Schaltplan schreiben,

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

Dies ist eine schöne Form, was bedeutet, dass eine fehlertolerante Steuerung NICHT realisiert wurde. Wie Sie sehen können, breitet sich das im Codeblock A erzeugte Bitinversionsrauschen zum Codeblock B aus. Es ist jedoch in Ordnung, da es sich nicht innerhalb desselben Blocks ausbreitet. Das im Codeblock B erzeugte Phaseninversionsrauschen breitet sich auch auf den Codeblock A aus, dies wird jedoch auch nicht auf denselben Block übertragen, so dass es in Ordnung ist (Fehler können in jedem Block korrigiert werden).

Phasenschieber: T.

Dies vervollständigt das Clifford-Tor. Ein weiteres Phasenverschiebungsgatter, das $ T $ -Gatter, wird benötigt, um die Quantenberechnung universell zu machen. Das $ T $ Gate ist

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

Da es durch definiert ist, geben Sie den Vorzeichenstatus $ \ ket {\ psi} = a \ ket {0_L} + b \ ket {1_L} $ und $ \ ket {\ psi ^ {\ prime}} = a \ ket ein Es wäre schön, wenn die Fehlertoleranz für Operationen konfiguriert werden könnte, die {0_L} + ^ {i \ pi / 4} \ ket {1_L} $ ausgeben. Das ist aber nicht so einfach. Es ist ein kluger Weg [^ 5], der etwas verwirrend ist, also gebe ich Ihnen zuerst die Antwort. Der Schaltplan ist

[^ 5]: [Übung 10.65] und "Übung 10.66" von Neilsen, Chan beschreiben, wie diese Schaltung abgeleitet wird. Wenn ich diese Übung versuche, sehe ich! Es wird so sein. In Übung 10.68 wird auch beschrieben, wie Sie das Toffoli-Gate auf ähnliche Weise als fehlertolerant konfigurieren.

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

ist. Was bedeutet es, dass der erste Codeblock das $ T $ enthält, das wir definieren werden? Du hast vielleicht gedacht. Stellen Sie sich die ersten Adamal- und $ T $ -Gatter in diesem ersten Codeblock als einen Effekt vor, der einen ähnlichen Zustand wie diese Berechnung ausspuckt. In der Abbildung habe ich $ \ ket {C} $ geschrieben,

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

Es wird sein. Ich werde später erklären, wie dieser Zustand erstellt wird, aber ich werde die nächste Operation unter der Annahme erläutern, dass ein solcher Zustand erstellt wird. Wenden Sie zuerst die Kontrolle NICHT an. Dies ist die fehlertolerante Steuerung, die Sie NICHT gerade konfiguriert haben. Eine fehlertolerante Steuerung NOT kann so behandelt werden, als ob die Basis eine logische Basis in der mathematischen Formel ist.

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

Kann geschrieben werden. Daher ist die Auswirkung von CNOT auf $ \ ket {C} \ ket {\ psi} $

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

Es wird sein. Wenn der zweite Codeblock gemessen wird und der gemessene Wert $ 1 (\ ket {0_L}) $ ist, wird nichts unternommen, sodass die Ausgabe des ersten Codeblocks erfolgt

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

Es wird sein. Wenn der gemessene Wert $ -1 (\ ket {1_L}) $ ist, wird $ SX $ berechnet, so dass der Zustand von Gleichung (27) multipliziert mit der globalen Phase als erster Codezustand ausgegeben wird. ..

Nun, es gab eine Erklärung, wie man den Zustand wie Gleichung (24) ausspuckt. In Anbetracht des Stabilisatorformats ist die Konvertierung von $ \ ket {0_L} $ nach $ TH \ ket {0_L} $ $ \ bar {Z} \ rightarrow \ bar {T} \ bar {H} \ bar {Z} \ bar Es kann ausgedrückt werden als {H} \ bar {T} ^ {\ Dolch} $ und kann ausgedrückt werden als $ \ bar {T} \ bar {H} \ bar {Z} \ bar {H} \ bar {T} ^ {\ Dolch } $ Is

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

Es kann umgeschrieben werden als. Daher ist der Status $ \ ket {C} $ ein eindeutiger Status für den eindeutigen Wert $ + 1 $ des Operators $ e ^ {-i \ pi / 4} \ bar {S} \ bar {X} $. Dies bedeutet, dass $ e ^ {-i \ pi / 4} \ bar {S} \ bar {X} $ indirekt gemessen wird, und wenn der gemessene Wert $ + 1 $ erhalten wird, ist es $ \ ket {C} $. Es wird gut sein wie. Wenn der gemessene Wert $ -1 $ ist, wenden Sie $ \ bar {Z} $ an. Dann wechselt es in den Zustand des Eigenwerts $ + 1 $ [^ 6].

[^ 6]: $ \ bar {Z} $ ist gegenkonvertierbar in $ e ^ {-i \ pi / 4} \ bar {S} \ bar {X} $, also $ \ bar {Z} \ frac { 1} {2} (dh ^ {-i \ pi / 4} \ bar {S} \ bar {X}) \ ket {0_L} = \ frac {1} {2} (I + e ^ {-i \ Es wird pi / 4} \ bar {S} \ bar {X}) \ ket {0_L} $, und der eindeutige Wert kann umgekehrt werden.

Hier gibt es eine Einschränkung. Ich sagte, dass $ e ^ {-i \ pi / 4} \ bar {S} \ bar {X} $ indirekt gemessen wird, aber ein wenig Einfallsreichtum erforderlich ist. Schematisch

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

Das Problem ist jedoch das kontrollierte $ e ^ {-i \ pi / 4} I $ Gate. das ist,

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

Verwendung der Gleichung

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

Es ist gut, es in die Form von zu verwandeln. Das $ T $ -Tor in dieser Figur ist nur ein $ T $ -Tor.

Jetzt haben wir also ein $ T $ -Tor für den signierten Status. Die $ CNOT-, S- und X $ -Gatter können alle transversal sein, sodass sie insgesamt fehlertolerant sind. Die Messung wurde jedoch nicht berücksichtigt. Man kann sagen, dass das $ T $ -Gatter, das wirklich fehlertolerant ist, nur realisiert werden kann, wenn das Messteil auch fehlertolerant gemacht wird.

Lassen Sie uns als nächstes über fehlertolerante Messungen sprechen.

Messung

Die indirekte Messung des Operators $ ABC $, der mit dem vorzeichenbehafteten Zustand arbeitet, ist

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

Sie können dies tun, indem Sie Folgendes tun (Da es sich um eine Steane-Code-Prämisse handelt, sind tatsächlich 7 Zeilen für den Codeblock erforderlich, der Einfachheit halber werden jedoch 3 Zeilen weggelassen). Unter dem Gesichtspunkt der Fehlertoleranz ist dies jedoch eine sehr schlechte Idee. Wenn die Hilfsbits verrauscht sind, kann sich das Rauschen auf alle Bits ausbreiten, aus denen der Codeblock besteht. Um dies zu vermeiden, wissen wir, dass die folgende Konfiguration verwendet werden sollte.

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

Setzen Sie das Hilfsbit auf 3 Bit

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

Diese Schaltung erzeugt den sogenannten Katzenzustand $ (\ ket {000} + \ ket {111}) / \ sqrt {2} $. Auf diese Weise kann eine indirekte Messung erreicht werden, und selbst wenn Rauschen in den Hilfsbits auftritt, breitet sich das Rauschen nur auf ein Bit des Codeblocks aus.

Dies ist in Ordnung, kann jedoch beim Erstellen des ersten Katzenzustands laut sein. Wenn in einem der 3 Hilfsbits Rauschen auftritt, breitet sich das Rauschen leicht im Block aus. Was soll ich machen? Wenn Sie in einem solchen Fall einen Katzenstatus erstellen, müssen Sie überprüfen, ob er korrekt ausgeführt wurde. Wenn dies nicht korrekt ist, verwerfen Sie diesen Status und versuchen Sie, ihn erneut zu erstellen. Insbesondere wird die Paritätsprüfschaltung unmittelbar nach dem Erstellen des Katzenzustands eingefügt.

Paritätsprüfung
      |0> --X--X-- M
            |  |
|0> --H--*--*--|--*----------*--H-- M
    -----X-----*--|--*-------X-----
    -----X--------|--|--*----X-----
                  |  |  |
    --------------A--|--|----------
    -----------------A--|----------
    --------------------A----------

Es ist so. Der Einfachheit halber habe ich nur eine Paritätsprüfung geschrieben, aber da diese mit allen Bitkombinationen geprüft werden sollte, ist auch die Paritätsprüfung des zweiten und dritten Bits erforderlich. Wiederholen Sie die Erstellung des Katzenzustands, bis die gesamte Parität zu einer gleichmäßigen Parität wird.

Es ist ein bisschen schwierig, aber jetzt ist es fehlertolerant! Ich würde gerne sagen, aber es gibt noch ein anderes Problem. Sie sollten auch berücksichtigen, dass in den zur Paritätsprüfung hinzugefügten Hilfsbits Phaseninversionsrauschen auftritt. In diesem Fall breitet es sich zur indirekten Messung auf zwei Bits des 3-Bit-Blocks aus. Dies kann Fehler nicht korrigieren. Infolgedessen gibt die Messung ganz rechts das falsche Ergebnis aus. Auch in diesem Fall kann nicht geholfen werden. Wiederholen Sie die Messung daher dreimal, um eine Mehrheit zu erhalten. Dann kann die Fehlerrate auf $ O (p ^ 2) $ unterdrückt werden (vorausgesetzt, die Wahrscheinlichkeit des Auftretens von Rauschen beträgt $ p $).

Sie haben jetzt eine fehlertolerante Messung konfiguriert. Die Messung ist nicht nur zur Erfassung des Berechnungsergebnisses erforderlich, sondern auch für die zuvor erläuterte Syndrommessung zur Fehlerkorrektur und zur Erzeugung des $ T $ -Gatters sowie für den nachfolgend beschriebenen Ausgangszustand. Ist was wird.

Erstzustandserstellung

Lassen Sie uns also darüber sprechen, wie die Erstellung des Anfangszustands fehlertolerant konfiguriert wird. Letztes Mal, Letztes Mal Anfangszustand von 5 Quantenbitcode (logische Basis) Wir haben ausführlich beschrieben, wie der Status $ \ ket {0_L} $) erstellt wird. Ersetzen Sie es einfach durch den Steane-Code und ersetzen Sie das indirekte Messteil durch die soeben beschriebene fehlertolerante Messung.

Die sechs Quellen des Steane-Codes und der logische $ Z $ -Operator wurden bereits früher vorgestellt. Um den Anfangszustand zu erstellen, werden diese 7 Operatoren der Reihe nach gemessen und nacheinander auf den Eigenraum mit dem Eigenwert von $ + 1 $ projiziert, aber sie werden mit dem Eigenwert von $ -1 $ auf den Eigenraum projiziert. In diesem Fall wäre es besser gewesen, einen Operator anzuwenden, der mit der relevanten Quelle nicht austauschbar und mit anderen Quellen kompatibel ist. Im Fall von Steane-Code gibt es die folgenden 7 Operatoren [^ 7]. Ich werde es hier veröffentlichen, da es später bei der Überprüfung des Vorgangs benötigt wird.

[^ 7]: Ich denke, es gibt andere Optionen, aber ich habe diejenigen aufgelistet, die ich als Beispiel gefunden habe.

Operator
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

Jetzt wissen Sie, wie Sie den gesamten für die Quantenberechnung erforderlichen Prozess (Erstellung des Anfangszustands, Gate-Berechnung, Messung) fehlertolerant konfigurieren.

Die nächste Frage ist nun, wie klein die Fehlerrate der Quantenberechnung sein kann. Unter der Annahme, dass die Fehlerwahrscheinlichkeit in jeder Komponente des Systems $ p $ beträgt, kann die Fehlerrate des Berechnungsergebnisses auf höchstens $ O (p ^ 2) $ unterdrückt werden, aber wie klein kann sie sein? Ist das? Wenn $ p $ unter einem bestimmten Schwellenwert liegt, gibt es eine Möglichkeit, ihn so klein zu machen, wie Sie möchten. Ich werde das unten erklären.

Verkettungscode und Schwellenwertsatz

Die Komponenten, aus denen das Quantencomputersystem besteht, umfassen ein Quantenbit, eine Steuervorrichtung, die es steuert, eine Messvorrichtung zum Messen des Quantenzustands usw., und jede von ihnen empfängt eine Fehlfunktion oder ein Rauschen von der Außenwelt und ist vorbestimmt. Es besteht eine gewisse Wahrscheinlichkeit, dass es nicht funktioniert. Nehmen wir ganz einfach an, dass die durchschnittliche Wahrscheinlichkeit $ p $ ist. Wie in den vorherigen Abschnitten erläutert, kann höchstens ein Fehler pro Codeblock korrigiert werden. Das Problem besteht darin, dass zwei Fehler gleichzeitig auftreten und sich ausbreiten, um zwei Fehler in einen bestimmten Codeblock zu übertragen. Seine Wahrscheinlichkeit ist proportional zu $ p ^ 2 $ und ist $ cp ^ 2 $. Dieser Proportionalitätskoeffizient $ c $ ist die Zahl im Fall von "zwei Fehler in einem bestimmten Codeblock verursachen". Neilsen, Chan sagt $ c \ ca. 10 ^ {4} $ als sehr grobe Schätzung am Beispiel einer einfachen Quantenschaltung. Der Wert wird gebucht.

Um diese Fehlerrate zu verringern, sollten Sie jedes Quantenbit, das den Codeblock und den Hilfsblock zur Fehlerkorrektur bildet, weiter codieren. Da 1 Bit des ursprünglichen Systems nach dem Steane-Code 7-mal + $ \ alpha $ war, ist es weitere 7-mal + $ \ alpha $. Der Maßstab des Systems wird zunehmen, aber dank dessen wird die Fehlerrate $ c (cp ^ 2) ^ 2 = c ^ {3} p ^ {4} $ sein. Wenn jedes Bit mit einem Steane-Code codiert ist, beträgt die Systemskala erneut das 7-fache von + $ \ alpha $, und die Fehlerrate beträgt $ c (c (cp ^ 2) ^ 2) ^ 2 = c ^ {7} p ^. Es wird {8} $ sein. Wenn diese Operation $ k $ mal wiederholt wird, beträgt die Systemskala (erforderliche Anzahl von Bits) $ d ^ k $, wenn die ursprüngliche Systemskala $ d $ ist, und die Fehlerrate beträgt $ (cp) ^ {2. Es wird ^ k} / c $ sein. Das hierarchische Konstruieren der Codierung auf diese Weise wird als "verketteter Code" bezeichnet.

Angenommen, das Quantencomputersystem, an das Sie denken, hat ursprünglich $ p (n) $ Gates. Angenommen, $ n $ repräsentiert die Größe eines Problems und $ p (n) $ ist eine polymorphe Funktion für $ n $. Wenn die Fehlerrate, die Sie am Ende erreichen möchten, $ \ epsilon $ ist,

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

Die Beziehung muss hergestellt werden. Wie Sie sehen können, können Sie die Fehlerrate so weit reduzieren, wie Sie möchten, wenn $ p $ einen bestimmten Schwellenwert $ p_ {th} <1 / c $ erreicht, indem Sie den Wert von $ k $ groß genug machen. Als grobe Schätzung war es $ c \ ca. 10 ^ {4} $, also $ p_ {th} \ ca. 10 ^ {-4} = 0,01 % $.

Welche Systemgröße (Anzahl der Bits) $ d ^ k $ ist erforderlich, um die Fehlerrate $ \ epsilon $ zu erreichen? Sie kann gefunden werden, indem die Ungleichung in Gleichung (27) durch eine Näherung ersetzt und wie folgt transformiert wird.

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

Die Anzahl der darin enthaltenen Tore beträgt

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

Kann geschätzt werden. Das heißt, eine Quantenschaltung, die $ p (n) $ Gatter enthält, hängt von der Hardware ab, deren Komponentenfehlerwahrscheinlichkeit höchstens $ p $ beträgt.

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

Eine Fehlerrate von $ \ epsilon $ kann mit mehreren Gates erreicht werden. $ P $ muss jedoch unter einem bestimmten Schwellenwert liegen. Dies wird als "Schwellensatz" bezeichnet.

Funktionsprüfung

Nachdem ich die Theorie verstanden habe, möchte ich ein sehr einfaches Beispiel für eine fehlertolerante Quantenberechnung nehmen und die Funktionsweise mit dem Quantenberechnungssimulator qlazy überprüfen. Ich habe oben erklärt, wie man das $ T $ Gate fehlertolerant macht, aber ich fand es etwas schwierig, also mal sehen, ob das wirklich funktioniert. Selbst wenn das $ T $ -Gatter auf den Status $ \ ket {0_L} $ angewendet wird, bleibt es $ \ ket {0_L} $ und ist überhaupt nicht interessant. Wenden Sie also Adamar hin und her und $ \ bar {H} \ bar {an Führen Sie die Operation T} \ bar {H} \ ket {0_L} $ aus und messen Sie schließlich mit der Basis $ \ bar {Z} $. Derzeit sind alle Gate-Operationen und -Messungen fehlertolerant konfiguriert. Ich habe jedoch auf das Hinzufügen von Rauschen und das Korrigieren des Fehlers verzichtet (seit ich es das letzte Mal getan habe). Darüber hinaus haben wir die Paritätsprüfung weggelassen, um zu überprüfen, ob der Katzenzustand korrekt ist, und die Methode, viele Male zu messen und eine Mehrheitsentscheidung zu treffen. Dieses Mal konzentrierte ich mich jedoch nur darauf, zu bestätigen, dass die Arithmetik und Messung für den Codezustand in der fehlertoleranten Konfiguration korrekt realisiert wurde.

Implementierung

Schauen wir uns nun den gesamten Python-Code an.

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)

Ich werde kurz erklären, was Sie tun. Schauen Sie sich zunächst den Hauptverarbeitungsabschnitt an.

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

Wir erstellen also den logischen Basiszustand $ \ ket {0_L} $ des Steane-Codes. Die Details befinden sich in der Funktion static_zero, können jedoch sehr lang und verwirrend sein. Aber die Grundlagen sind einfach,

# 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)

Es ist eine Wiederholung des Codes wie. Das Hilfsbit wird auf den Cat-Zustand gesetzt und die Quelle indirekt gemessen. Wenn das Messergebnis 1 ist (dh $ \ ket {1_L} $), wird der Operator angewendet, der mit der Quelle nicht austauschbar ist. Wenn alle sieben Operatoren abgeschlossen sind, wird der Status zurückgegeben (mit Ausnahme der Hilfsbits). Hier besteht die letzte Methode zum Abrufen des Messwerts darin, die Binärzeichenfolge abzurufen (hinzugefügt in Version 0.0.41). Nächster,

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

Also wende ich den fehlertoleranten Adamar an. Es ist ein transversaler Typ, also ist es einfach.

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

Und ich verwende ein fehlertolerantes $ T $ -Tor. Werfen wir einen Blick auf den Inhalt der Funktion errortolerant_t. Der oben erläuterte erste Codeblock heißt B, der zweite Codeblock heißt C und der für die Messung erforderliche Hilfsblock heißt A. Jedes besteht aus 7 Bits. Ich hoffe, Sie können es vor Ort sehen.

# -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)

Erstellt den gleichen Vorzeichenstatus wie beim Anwenden von $ H $ und $ T $. Ich setze das Hilfsbit auf den Zustand cat und messe den Operator $ e ^ {-i \ pi / 4} SX $, aber da der Transversaltyp von $ S $ $ ZS $ war, steuere ich $ ZSX $. werde ich so machen. Da die Phase $ e ^ {-i \ pi / 4} $ gleich dem $ T $ -Gatter auf der Steuerseite war, erinnere ich mich daran, diese Berechnung einzubeziehen.

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

Machen Sie also einen transversalen CNOT,

# -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]

Wenn der Codeblock C gemessen wird und das Messergebnis 1 ist, wird $ SX $ auf den Codeblock A angewendet. Denken Sie auch hier daran, dass der transversale Typ von $ S $ $ ZS $ war. Das Ergebnis sollte im Codeblock B sein.

qs_out = qs_ABC.partial(qid=B)

Das dem Codeblock B entsprechende Teilsystem wird also durch das Teilverfahren herausgenommen. Ich werde das zurückgeben.

Kehren Sie zum Hauptverarbeitungsabschnitt zurück.

Für das Ergebnis des $ T $ Gates

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

Berechnen Sie Adamar erneut als fehlertolerant und schließlich als

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

Führen Sie dann die Messung durch. Einzelheiten finden Sie im Inhalt der Funktion errortolerant_m. Es ist nur eine indirekte Messung mit dem Hilfsbit im Katzenzustand. Das Messergebnis wird als Variable md (eine Instanz der MData-Klasse) erfasst, und die Frequenzdaten werden im Zählerformat mit der Frequenzmethode (hinzugefügt in v0.0.41) erhalten. das ist alles.

Ergebnis

Das Ausführungsergebnis ist unten dargestellt.

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

Die ersten beiden Zeilen sind das Ergebnis eines normalen -H-T-H-, das nicht fehlertolerant ist. Das ist die Antwort. Dies bedeutet, dass die Wahrscheinlichkeiten für die Zustände $ \ ket {0_L} $ und $ \ ket {1_L} $ 0,8536 bzw. 0,1464 betragen. Der Zähler in der 3. Zeile ist das Ergebnis der Ausführung des fehlertoleranten -H-T-H- und der 10000-fachen Simulation. Ich denke, es entspricht ungefähr der Wahrscheinlichkeit der Antwort (denken Sie!).

abschließend

Ich fand heraus, dass die fehlertolerante Quantenberechnung eine sehr schwierige Technik ist, wenn verschiedene Techniken vollständig genutzt werden. Um einen wirklich praktischen Quantencomputer herzustellen, ist diese Art der stetigen Akkumulation wichtig, nicht wahr? Der Schwellenwertsatz war eine überaus wichtige theoretische Leistung, die als unterstützend bezeichnet werden kann und die garantiert, dass der Aufwand mit Sicherheit belohnt wird. Trotzdem ist die Fehlerrate von $ 10 ^ {-4} = 0,01 % $ eine strenge Anforderung. Unter der Annahme eines Fehlerkorrekturcodes wie eines Stabilisatorcodes und eines Verkettungscodes ist diese Genauigkeit unbedingt erforderlich. Es scheint jedoch, dass dieser Schwellenwert durch Verwendung einer anderen Codierungsmethode erhöht werden kann. Das nächste Mal möchte ich eine solche Codierungsmethode untersuchen, "topologischen Code (Oberflächencode)".

das ist alles

Recommended Posts

Grundlagen der Quanteninformationstheorie: Fehlertolerante Quantenberechnung
Grundlagen der Quanteninformationstheorie: Entropie (2)
Grundlagen der Quanteninformationstheorie: Datenkomprimierung (1)
Grundlagen der Quanteninformationstheorie: Horebaud-Grenzen
Grundlagen der Quanteninformationstheorie: Spurenentfernung
Grundlagen der Quanteninformationstheorie: Quantenzustands-Tomographie
Grundlagen der Quanteninformationstheorie: Datenkomprimierung (2)
Grundlagen der Quanteninformationstheorie: Topologische Oberflächencodes
Grundlagen der Quanteninformationstheorie: Quantenfehlerkorrektur (Shor Code)
Grundlagen der Quanteninformationstheorie: Quantenfehlerkorrektur (CSS-Code)
Grundlagen der Quanteninformationstheorie: Quantenfehlerkorrektur (Stabilisatorcode: 4)
Grundlagen der Quanteninformationstheorie: Quantenfehlerkorrektur (klassischer linearer Code)
Grundlagen der Quanteninformationstheorie: Universelle Quantenberechnung durch Oberflächencode (1)
Lesen Sie "Grundlagen des Quantenglühens", Tag 5
Grundlagen der Tableau-Grundlagen (Visualisierung mit geografischen Informationen)
Python-Grundlagen ①
Grundlagen von Python ①