Deutschs Algorithmus
Deutschs Algorithmus löst das Paritätsproblem für den Spezialfall . Im Kontext des Quantencomputings wird dieses Problem manchmal als Deutschs Problem bezeichnet, und wir folgen dieser Bezeichnung in dieser Lektion.
Genauer gesagt wird die Eingabe durch eine Funktion von einem Bit auf ein Bit dargestellt. Es gibt vier solcher Funktionen:
Die erste und letzte dieser Funktionen sind konstant und die mittleren beiden sind balanciert, was bedeutet, dass die beiden möglichen Ausgabewerte der Funktion gleich oft auftreten, wenn wir alle Eingaben durchlaufen. Deutschs Problem besteht darin, zu bestimmen, zu welcher der beiden Kategorien die Eingabefunktion gehört: konstant oder balanciert.
Wenn wir die Eingabefunktion in Deutschs Problem als Direktzugriff auf eine Zeichenkette betrachten, denken wir über eine Zwei-Bit-Zeichenkette nach: .
So betrachtet ist Deutschs Problem die Berechnung der Parität (oder gleichwertig: des exklusiven ODER) der zwei Bits.
Jeder klassische Abfragealgorithmus, der dieses Problem korrekt löst, muss beide Bits abfragen: und . Wenn wir zum Beispiel wissen, dass gilt, könnte die Antwort immer noch oder sein, je nachdem ob oder gilt. Alle anderen Fälle sind ähnlich; wenn man nur eines der beiden Bits kennt, erhält man keinerlei Information über ihre Parität. Der im vorherigen Abschnitt beschriebene Boolesche Circuit ist also das Beste, was wir in Bezug auf die Anzahl der benötigten Abfragen zur Lösung dieses Problems tun können.
Quantencircuit-Beschreibung
Deutschs Algorithmus löst Deutschs Problem mit einer einzigen Abfrage und bietet damit einen messbaren Vorteil von Quanten- gegenüber klassischen Berechnungen. Das mag ein bescheidener Vorteil sein – eine Abfrage statt zwei –, aber irgendwo muss man anfangen. Wissenschaftliche Fortschritte haben manchmal scheinbar bescheidene Ursprünge.
Hier ist ein Quantencircuit, der Deutschs Algorithmus beschreibt:
Analyse
Um Deutschs Algorithmus zu analysieren, verfolgen wir die Wirkung des obigen Circuits und identifizieren die Zustände der Qubits zu den in dieser Abbildung vorgeschlagenen Zeitpunkten:
Der Anfangszustand ist , und die beiden Hadamard-Operationen auf der linken Seite des Circuits transformieren diesen Zustand zu
(Wie immer folgen wir Qiskits Qubit-Ordnungskonvention, bei der das obere Qubit rechts und das untere Qubit links steht.) Es mag sich unintuitiv anfühlen, diesen Produktzustand teilweise verteilt zu schreiben (wobei die Zustände von Qubit 1 ausgefaktorisiert bleiben), aber das wird unsere späteren Ausdrücke kompakter machen.
Als Nächstes wird das -Gate ausgeführt. Gemäß der Definition des -Gates wird der Wert der Funktion für den klassischen Zustand des oberen/rechtesten Qubits mit dem unteren/linkesten Qubit XOR-verknüpft, was in den Zustand transformiert:
Wir können diesen Ausdruck vereinfachen, indem wir beobachten, dass die Formel
für beide möglichen Werte gilt. Expliziter sind die zwei Fälle wie folgt.
Damit können wir alternativ so ausdrücken:
Etwas Interessantes ist gerade passiert! Obwohl die Wirkung des -Gates auf Standard-Basiszustände das obere/rechteste Qubit unverändert lässt und den Funktionswert mit dem unteren/linkesten Qubit XOR-verknüpft, sehen wir hier, dass sich der Zustand des oberen/rechtesten Qubits (im Allgemeinen) geändert hat, während der Zustand des unteren/linkesten Qubits unverändert geblieben ist – er ist sowohl vor als auch nach der Ausführung des -Gates im Zustand . Dieses Phänomen ist als Phase Kickback bekannt, und wir werden gleich mehr darüber sagen.
Mit einer letzten Vereinfachung, nämlich dem Herausziehen des Faktors aus der Summe, erhalten wir diesen Ausdruck für den Zustand :
Beachte, dass wir in diesem Ausdruck im Exponenten von haben statt , was man aus rein algebraischer Sicht erwarten könnte, aber wir erhalten in beiden Fällen dasselbe Ergebnis. Das liegt daran, dass der Wert für eine ganze Zahl nur davon abhängt, ob gerade oder ungerade ist.
Das Anwenden des abschließenden Hadamard-Gates auf das obere Qubit hinterlässt uns mit dem Zustand
was mit Wahrscheinlichkeit zum korrekten Ergebnis führt, wenn das rechte/oberste Qubit gemessen wird.
Weitere Bemerkungen zum Phase Kickback
Bevor wir weitermachen, betrachten wir die obige Analyse aus einem etwas anderen Blickwinkel, der das Phase-Kickback-Phänomen beleuchten kann.
Zunächst beachte, dass die folgende Formel für alle Bits gilt.
Das kann überprüft werden, indem man es für die zwei möglichen Werte und prüft:
Mit dieser Formel sehen wir, dass
für jede Wahl von Bits gilt. Da diese Formel für und gilt, sehen wir durch Linearität, dass
für alle Qubit-Zustandsvektoren gilt, und daher
Der Schlüssel, der das funktionieren lässt, ist, dass gilt. Mathematisch gesprochen ist der Vektor ein Eigenvektor der Matrix mit dem Eigenwert .
Eigenvektoren und Eigenwerte werden wir in der bevorstehenden Lektion über Phasenschätzung und Faktorisierung ausführlicher besprechen, wo das Phase-Kickback-Phänomen auf andere unitäre Operationen verallgemeinert wird.
Unter Berücksichtigung, dass Skalare sich frei durch Tensorprodukte bewegen, finden wir eine alternative Weise zu erklären, wie die Operation in der obigen Analyse in transformiert:
Implementierung in Qiskit
Schauen wir nun, wie Deutschs Algorithmus in Qiskit implementiert werden kann. Wir beginnen mit einer Versionsüberprüfung und führen dann die für diese Implementierung erforderlichen Importe durch. Für die Implementierungen der anderen Algorithmen, die folgen, werden wir die erforderlichen Importe separat durchführen, um eine bessere Modularität zu gewährleisten.
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-aer
from qiskit import __version__
print(__version__)
2.1.1
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
Zuerst definieren wir einen Quantencircuit, der ein Abfrage-Gate für eine der vier Funktionen oder von einem Bit auf ein Bit implementiert, wie zuvor beschrieben. Wie bereits erwähnt, ist die Implementierung von Abfrage-Gates kein eigentlicher Teil von Deutschs Algorithmus; hier zeigen wir im Grunde nur eine Möglichkeit, die Eingabe in Form einer Circuit-Implementierung eines Abfrage-Gates vorzubereiten.
def deutsch_function(case: int):
# This function generates a quantum circuit for one of the 4 functions
# from one bit to one bit
if case not in [1, 2, 3, 4]:
raise ValueError("`case` must be 1, 2, 3, or 4.")
f = QuantumCircuit(2)
if case in [2, 3]:
f.cx(0, 1)
if case in [3, 4]:
f.x(1)
return f
Wir können sehen, wie jeder Circuit mit der draw-Methode aussieht. Hier ist der Circuit für die Funktion .
display(deutsch_function(3).draw(output="mpl"))
Als Nächstes erstellen wir den eigentlichen Quantencircuit für Deutschs Algorithmus, wobei wir das Abfrage-Gate durch eine Quantencircuit-Implementierung ersetzen, die als Argument übergeben wird. Gleich werden wir einen der vier durch die zuvor definierte Funktion deutsch_function definierten Circuits einstecken.
Barrieren sind enthalten, um die visuelle Trennung zwischen der Abfrage-Gate-Implementierung und dem Rest des Circuits zu zeigen.
def compile_circuit(function: QuantumCircuit):
# Compiles a circuit for use in Deutsch's algorithm.
n = function.num_qubits - 1
qc = QuantumCircuit(n + 1, n)
qc.x(n)
qc.h(range(n + 1))
qc.barrier()
qc.compose(function, inplace=True)
qc.barrier()
qc.h(range(n))
qc.measure(range(n), range(n))
return qc
Auch hier können wir sehen, wie der Circuit mit der draw-Methode aussieht.
display(compile_circuit(deutsch_function(3)).draw(output="mpl"))
Schließlich erstellen wir eine Funktion, die den zuvor definierten Circuit einmal ausführt und das entsprechende Ergebnis ausgibt: „constant" oder „balanced".
def deutsch_algorithm(function: QuantumCircuit):
# Determine if a one-bit function is constant or balanced.
qc = compile_circuit(function)
result = AerSimulator().run(qc, shots=1, memory=True).result()
measurements = result.get_memory()
if measurements[0] == "0":
return "constant"
return "balanced"
Wir können Deutschs Algorithmus nun auf jede der vier oben definierten Funktionen anwenden.
f = deutsch_function(3)
display(deutsch_algorithm(f))
'balanced'