Klassische Berechnungen auf Quantencomputern
Wir wenden uns nun der Implementierung klassischer Algorithmen auf Quantencomputern zu. Wir werden sehen, dass jede Berechnung, die mit einem klassischen Booleschen Circuit durchgeführt werden kann, auch von einem Quantencircuit mit ähnlichen asymptotischen Berechnungskosten durchgeführt werden kann. Darüber hinaus kann dies auf eine „saubere" Weise geschehen, die gleich beschrieben wird und eine wichtige Voraussetzung für die Verwendung dieser Berechnungen als Unterroutinen in größeren Quantenberechnungen ist.
Simulation Boolescher Circuits mit Quantencircuits
Boolesche Circuits bestehen aus AND-, OR-, NOT- und FANOUT-Gates. Um Boolesche Circuits mit Quantencircuits zu simulieren, zeigen wir zunächst, wie jedes dieser vier Gates durch Quanten-Gates simuliert werden kann. Danach ist die Umwandlung eines gegebenen Booleschen Circuits in einen Quantencircuit eine einfache Angelegenheit: Gate für Gate simulieren. Dafür brauchen wir nur NOT-Gates, controlled-NOT-Gates und Toffoli-Gates – allesamt deterministische und unitäre Operationen.
Toffoli-Gates
Toffoli-Gates können alternativ als controlled-controlled-NOT-Gates beschrieben werden, deren Wirkung auf Standard-Basiszustände in der folgenden Abbildung dargestellt ist.
Mit der Qiskit-Konvention im Hinterkopf, bei der die Qubits von oben nach unten in aufsteigender Bedeutung geordnet sind, lautet die Matrixdarstellung dieses Gates wie folgt.
Eine andere Sichtweise auf Toffoli-Gates ist, dass sie im Wesentlichen Abfrage-Gates für die AND-Funktion sind, in dem Sinne, dass sie dem Muster folgen, das wir in der vorherigen Lektion für unitäre Abfrage-Gate-Implementierungen beliebiger Funktionen mit binären Zeichenketten als Ein- und Ausgabe gesehen haben.
Toffoli-Gates sind nicht im zuvor besprochenen Standard-Gate-Satz enthalten, aber es ist möglich, ein Toffoli-Gate aus -, -, - und CNOT-Gates wie folgt zu konstruieren.
Simulation Boolescher Gates mit Toffoli-, controlled-NOT- und NOT-Gates
Ein einzelnes Toffoli-Gate kann in Verbindung mit einigen NOT-Gates ein AND- und ein OR-Gate implementieren, und FANOUT-Gates lassen sich leicht mit controlled-NOT-Gates implementieren, wie die folgenden Diagramme zeigen.
In allen drei Fällen kommen die Qubits, auf die AND-, OR- und FANOUT-Gates wirken, von links als Eingaben, und für jedes Gate benötigen wir außerdem ein Hilfs-Qubit, das auf den Nullzustand initialisiert ist. Diese Hilfs-Qubits erscheinen innerhalb der Boxen, die die Gate-Implementierungen darstellen, um anzudeuten, dass sie neu sind und daher zu den Kosten dieser Implementierungen gehören.
Bei den AND- und OR-Gates haben wir neben dem Ausgabe-Qubit auch zwei weitere Qubits übrig. Zum Beispiel befinden sich innerhalb der Box im Diagramm, die die Simulation eines AND-Gates darstellt, die beiden oberen Qubits in den Zuständen und . Diese Qubits werden als innerhalb der Boxen verbleibend dargestellt, da sie nicht mehr benötigt werden und nicht Teil der Ausgabe sind. Sie können zunächst ignoriert werden, obwohl wir uns bald wieder mit ihnen befassen werden.
Das verbleibende Boolesche Gate, das NOT-Gate, ist in unserem Standard-Satz von Quanten-Gates enthalten, sodass wir dafür keine Simulation benötigen.
Gate-für-Gate-Simulation Boolescher Circuits
Nehmen wir nun an, wir haben einen gewöhnlichen Booleschen Circuit namens , der aus AND-, OR-, NOT- und FANOUT-Gates besteht und Eingabebits sowie Ausgabebits hat. Sei die Anzahl der Gates in , und nennen wir die von berechnete Funktion , die die Form
für hat.
Betrachten wir nun, was passiert, wenn wir die AND-, OR- und FANOUT-Gates von nacheinander durchgehen und jedes durch die entsprechende oben beschriebene Simulation ersetzen, einschließlich der Hinzufügung der erforderlichen Hilfs-Qubits. Nennen wir den resultierenden Circuit und ordnen die Qubits von so, dass die Eingabebits von den oberen Qubits von entsprechen und die Hilfs-Qubits unten sind.
Hierbei ist die Anzahl der erforderlichen Hilfs-Qubits – eines für jedes AND-, OR- und FANOUT-Gate von – und ist eine Funktion der Form , die die Zustände der übrig gebliebenen Qubits beschreibt, die durch die Gate-Simulationen nach dem Ausführen von entstehen. In der Abbildung befinden sich die Qubits, die der Ausgabe entsprechen, oben und die verbleibenden, übrig gebliebenen Qubits, die speichern, unten. Wir können das erzwingen, wenn wir möchten, indem wir die Qubits mithilfe von SWAP-Gates umordnen, die mit drei controlled-NOT-Gates wie folgt implementiert werden können:
Wie wir im nächsten Abschnitt sehen werden, ist es nicht unbedingt notwendig, die Ausgabe-Qubits umzuordnen, aber es ist einfach genug zu tun, wenn wir es möchten.
Die Funktion , die die klassischen Zustände der übrig gebliebenen Qubits beschreibt, wird durch den Circuit bestimmt, aber wir müssen uns nicht allzu viel darum kümmern, in welchem Zustand sich diese Qubits am Ende der Berechnung befinden. Der Buchstabe folgt im Alphabet auf , was ein vernünftiger Name ist – aber es gibt einen besseren Grund, den Namen zu wählen: er steht für Garbage (Abfall).
Bereinigung des Abfalls
Wenn wir nur daran interessiert sind, die von einem gegebenen Booleschen Circuit berechnete Funktion mit einem Quantencircuit auszuwerten, müssen wir nicht weiter gehen als die soeben beschriebene Gate-für-Gate-Simulation. Das bedeutet, dass wir neben der Funktionsausgabe auch einen Haufen Abfall übrig behalten.
Dies reicht jedoch nicht aus, wenn wir klassische Berechnungen als Unterroutinen in größeren Quantenberechnungen verwenden wollen, denn diese Abfall-Qubits verursachen Probleme. Das Phänomen der Interferenz ist für Quantenalgorithmen von entscheidender Bedeutung, und Abfall-Qubits können die Interferenzmuster zerstören, die für das Funktionieren von Quantenalgorithmen notwendig sind.
Glücklicherweise ist es nicht schwer, den Abfall zu beseitigen. Der Schlüssel liegt darin, die Tatsache zu nutzen, dass wir , da es sich um einen Quantencircuit handelt, rückwärts ausführen können, indem wir jedes Gate durch seine Inverse ersetzen und sie in umgekehrter Reihenfolge anwenden, wodurch wir einen Quantencircuit für die Operation erhalten. Toffoli-Gates, CNOT-Gates und NOT-Gates sind tatsächlich ihre eigenen Inversen, sodass das Rückwärtsausführen von wirklich nur eine Frage der Anwendung der Gates in umgekehrter Reihenfolge ist – aber im Allgemeinen kann jeder Quantencircuit wie soeben beschrieben umgekehrt werden.
Konkret können wir weitere Qubits hinzufügen (unter Berücksichtigung, dass die Funktion Ausgabebits hat), CNOT-Gates verwenden, um die Ausgabe von auf diese Qubits zu kopieren, und umkehren, um den Abfall zu beseitigen. Die folgende Abbildung zeigt den resultierenden Circuit und beschreibt seine Wirkung auf Standard-Basiszustände.
Wenn wir eine Box um den gesamten Circuit legen und ihn nennen, sieht er so aus:
Da Gates hat, wird der Circuit Gates haben.
Wenn wir die zusätzlichen Hilfs-Qubits außer Acht lassen, haben wir einen Circuit , der genau wie ein Abfrage-Gate für die Funktion funktioniert. Wenn wir die Funktion für eine Zeichenkette berechnen wollen, können wir setzen, und der resultierende Wert erscheint auf den unteren Qubits – oder wir können einen anderen Zustand in die unteren Qubits einspeisen, wenn wir möchten (vielleicht um einen Phase-Kickback zu nutzen, wie bei Deutschs oder dem Deutsch-Jozsa-Algorithmus).
Das bedeutet, dass wir für jeden Abfragealgorithmus, wenn wir einen Booleschen Circuit haben, der die Eingabefunktion berechnet, jedes Abfrage-Gate durch eine Circuit-Implementierung ersetzen können, und der Abfragealgorithmus wird korrekt funktionieren.
Beachte, dass die Hilfs-Qubits notwendig sind, damit dieser Prozess funktioniert, aber sie werden nach der Ausführung des kombinierten Circuits in ihre Ausgangszustände zurückversetzt. Dadurch können diese Qubits erneut als Hilfs-Qubits für andere Zwecke verwendet werden. Es gibt auch bekannte Strategien, um die Anzahl der benötigten Hilfs-Qubits zu reduzieren (was auf Kosten größerer Circuits geht), aber wir werden diese Strategien hier nicht besprechen.
Implementierung invertierbarer Funktionen
Die soeben beschriebene Konstruktion ermöglicht es uns, jeden Booleschen Circuit auf abfallfreie Weise mit einem Quantencircuit zu simulieren. Wenn ein Boolescher Circuit ist, der eine Funktion implementiert, erhalten wir einen Quantencircuit , der auf Standard-Basiszuständen wie folgt wirkt.
Die Zahl gibt an, wie viele Hilfs-Qubits insgesamt benötigt werden. Dies ist für die Zwecke dieses Kurses ausreichend, aber es ist möglich, diese Methodik einen Schritt weiter zu treiben, wenn die Funktion selbst invertierbar ist.
Genauer gesagt, nehmen wir an, dass die Funktion die Form hat, und nehmen wir außerdem an, dass eine Funktion existiert, sodass für jedes gilt (die bei Existenz notwendigerweise eindeutig ist). Das bedeutet, dass die Operation, die für jedes in transformiert, unitär ist. Daher könnten wir hoffen, einen Quantencircuit zu konstruieren, der die durch
für jedes definierte unitäre Operation implementiert.
Um klar zu sein: Die Tatsache, dass dies eine unitäre Operation ist, beruht darauf, dass invertierbar ist – sie ist nicht unitär, wenn nicht invertierbar ist. Abgesehen von den Hilfs-Qubits unterscheidet sich von der Operation, die der Circuit implementiert, weil wir keine Kopie der Eingabe aufbewahren und mit einer beliebigen Zeichenkette XOR-verknüpfen, sondern durch ersetzen.
Die Frage ist: Wenn invertierbar ist, können wir das tun?
Die Antwort ist ja, vorausgesetzt, wir dürfen Hilfs-Qubits verwenden und haben neben einem Booleschen Circuit, der berechnet, auch einen, der berechnet. Das ist also keine Abkürzung für die rechnerische Invertierung von Funktionen, wenn wir nicht bereits wissen, wie das geht! Das folgende Diagramm zeigt, wie es durch die Komposition zweier Quantencircuits und erfolgen kann, die individuell für die Funktionen und nach der oben beschriebenen Methode erhalten werden, zusammen mit SWAP-Gates, wobei das Maximum der Anzahlen der von und benötigten Hilfs-Qubits ist.