Der Deutsch-Jozsa-Algorithmus
Deutschs Algorithmus übertrifft alle klassischen Algorithmen für ein Abfrageproblem, aber der Vorteil ist recht bescheiden: eine Abfrage gegenüber zwei. Der Deutsch-Jozsa-Algorithmus erweitert diesen Vorteil - und er kann tatsächlich zur Lösung einer Reihe verschiedener Abfrageprobleme verwendet werden.
Hier ist eine Quantenschaltungsbeschreibung des Deutsch-Jozsa-Algorithmus. Ein zusätzlicher klassischer Nachbearbeitungsschritt, der in der Abbildung nicht dargestellt ist, kann je nach dem zu lösenden Problem ebenfalls erforderlich sein.
Natürlich haben wir noch nicht erörtert, welche Probleme dieser Algorithmus löst; dies wird in den beiden folgenden Abschnitten getan.
Das Deutsch-Jozsa-Problem
Wir beginnen mit dem Abfrageproblem, das der Deutsch-Jozsa-Algorithmus ursprünglich lösen sollte und das als Deutsch-Jozsa-Problem bekannt ist.
Die Eingabefunktion für dieses Problem hat die Form „ “ für eine beliebige positive ganze Zahl „ “. Ähnlich wie bei Deutschs Problem besteht die Aufgabe darin, „ “ auszugeben, wenn „ “ konstant ist, und „ “, wenn „ “ ausgeglichen ist, was wiederum bedeutet, dass die Anzahl der Eingabezeichenfolgen, für die die Funktion den Wert „ “ annimmt, gleich der Anzahl der Eingabezeichenfolgen ist, für die die Funktion den Wert „ “ annimmt.
Beachten Sie, dass es, wenn „ “ größer ist als „ “, Funktionen der Form „ “ gibt, die weder konstant noch ausgeglichen sind. Beispielsweise ist die Funktion „ “ wie folgt definiert:
fällt in keine dieser beiden Kategorien. Beim Deutsch-Jozsa-Problem kümmern wir uns einfach nicht um Funktionen wie diese - sie werden als "Don't Care"-Eingaben betrachtet. Das heißt, für dieses Problem haben wir eine Zusage, dass entweder konstant oder ausgeglichen ist.
Eingabe: eine Funktion \ Versprechen: ist entweder konstant oder ausgeglichen \ Ausgabe: wenn konstant ist, wenn ausgeglichen ist
Der Deutsch-Jozsa-Algorithmus löst dieses Problem mit einer einzigen Abfrage im folgenden Sinne: Wenn jedes der Messergebnisse ist, dann ist die Funktion konstant; andernfalls, wenn mindestens eines der Messergebnisse ist, dann ist die Funktion ausgeglichen. Man könnte es auch so formulieren: Auf die oben beschriebene Schaltung folgt ein klassischer Nachbearbeitungsschritt, bei dem die ODER-Verknüpfung der Messergebnisse berechnet wird, um das Ausgabebit des Deutsch-Jozsa-Problems zu erzeugen.
Algorithmusanalyse
Um die Leistung des Deutsch-Jozsa-Algorithmus für das Deutsch-Jozsa-Problem zu analysieren, ist es hilfreich, zunächst die Wirkung einer einzelnen Schicht von Hadamard-Gattern zu betrachten. Eine Hadamard-Operation kann auf die übliche Weise als Matrix ausgedrückt werden,
aber wir können diese Operation auch in Bezug auf ihre Wirkung auf Standard-Basiszustände ausdrücken:
Diese beiden Gleichungen können in einer einzigen Formel zusammengefasst werden,
was für beide Werte von gilt.
Nehmen wir nun an, dass wir anstelle eines einzelnen Qubits Qubits haben und für jedes eine Hadamard-Operation durchgeführt wird. Die kombinierte Operation an den Qubits wird durch das Tensorprodukt ( mal) beschrieben, das wir der Kürze und Klarheit halber als schreiben. Unter Verwendung der obigen Formel, gefolgt von einer Erweiterung und Vereinfachung, können wir die Wirkung dieser kombinierten Operation auf die Standard-Basiszustände der Qubits wie folgt ausdrücken:
Hier schreiben wir übrigens binäre Zeichenfolgen der Länge gemäß der Indizierungskonvention von Qiskit als und .
Diese Formel ist ein nützliches Hilfsmittel für die Analyse der obigen Quantenschaltung. Nachdem die erste Schicht von Hadamard-Gattern durchgeführt wurde, ist der Zustand der Qubits (einschließlich des linken/unteren Qubits, das getrennt vom Rest behandelt wird)
Wenn die Operation durchgeführt wird, wird dieser Zustand in
durch genau das gleiche Phänomen des Phasenrückschlags, das wir bei der Analyse von Deutschs Algorithmus gesehen haben.
Dann wird die zweite Schicht von Hadamard-Gattern ausgeführt, die (nach der obigen Formel) diesen Zustand umwandelt in
Dieser Ausdruck sieht etwas kompliziert aus, und ohne genauere Kenntnisse über die Funktion lassen sich nicht allzu viele Rückschlüsse auf die Wahrscheinlichkeiten für verschiedene Messergebnisse ziehen.
Glücklicherweise brauchen wir nur die Wahrscheinlichkeit zu wissen, dass jedes der Messergebnisse ist - denn das ist die Wahrscheinlichkeit, mit der der Algorithmus feststellt, dass konstant ist. Für diese Wahrscheinlichkeit gibt es eine einfache Formel.
Beachten Sie, dass diese Werte der Wahrscheinlichkeit entsprechen, den Zustand zu messen, und nicht direkt dem endgültigen klassischen Ausgabebit des Deutsch-Jozsa-Problems. Der Algorithmus gibt „ “ aus, wenn alle Messergebnisse „ “ lauten (was darauf hindeutet, dass „ “ konstant ist), und andernfalls „ “ (was darauf hindeutet, dass „ “ ausgeglichen ist).
Genauer gesagt: Ist konstant, dann gilt entweder für jede Zeichenkette , wobei in diesem Fall der Wert der Summe beträgt, oder für jede Zeichenkette , wobei in diesem Fall der Wert der Summe beträgt. Durch Division durch und Quadrierung des Absolutwerts erhält man .
Ist hingegen ausgeglichen, so nimmt bei der Hälfte der Zeichenfolgen den Wert an und bei der anderen Hälfte den Wert , sodass sich die Terme und in der Summe aufheben und der Wert übrig bleibt.
Wir kommen zu dem Schluss, dass der Algorithmus korrekt funktioniert, sofern das Versprechen eingehalten wird.
Klassische Schwierigkeit
Der Deutsch-Jozsa-Algorithmus funktioniert jedes Mal, gibt immer die richtige Antwort, wenn das Versprechen erfüllt ist, und erfordert eine einzige Abfrage. Wie verhält sich dies im Vergleich zu klassischen Abfragealgorithmen für das Deutsch-Jozsa-Problem?
Erstens: Jeder deterministische klassische Algorithmus, der das Deutsch-Jozsa-Problem korrekt löst, muss exponentiell viele Abfragen durchführen: im ungünstigsten Fall sind mehrere Abfragen erforderlich. Wenn ein deterministischer Algorithmus auf oder weniger verschiedene Zeichenketten abfragt und jedes Mal denselben Funktionswert erhält, dann sind beide Antworten möglich. Die Funktion könnte konstant sein, oder sie könnte ausgeglichen sein, aber durch Pech geben die Abfragen alle denselben Funktionswert zurück.
Die zweite Möglichkeit mag unwahrscheinlich erscheinen - aber bei deterministischen Algorithmen gibt es keine Zufälligkeit oder Unsicherheit, so dass sie bei bestimmten Funktionen systematisch versagen. In dieser Hinsicht haben wir also einen erheblichen Vorteil von Quanten- gegenüber klassischen Algorithmen.
Der Haken an der Sache ist jedoch, dass probabilistische klassische Algorithmen das Deutsch-Jozsa-Problem mit sehr hoher Wahrscheinlichkeit mit nur wenigen Abfragen lösen können. Insbesondere, wenn wir einfach ein paar verschiedene Zeichenketten der Länge zufällig auswählen und nach diesen Zeichenketten abfragen, ist es unwahrscheinlich, dass wir für alle den gleichen Funktionswert erhalten, wenn ausgeglichen ist.
Genauer gesagt: Wenn wir die Eingabezeichenfolgen gleichmäßig zufällig auswählen, berechnen und als Antwort geben, wenn die Funktionswerte alle gleich sind, und , wenn dies nicht der Fall ist, dann liegen wir immer richtig, wenn konstant ist, und liegen in dem Fall falsch, dass ausgeglichen ist, mit einer Wahrscheinlichkeit von gerade . Nehmen wir beispielsweise , dann liefert dieser Algorithmus mit einer Wahrscheinlichkeit von mehr als % die richtige Antwort.
Aus diesem Grund haben wir immer noch einen eher bescheidenen Vorteil von Quantenalgorithmen gegenüber klassischen Algorithmen - aber es ist dennoch ein quantifizierbarer Vorteil, der eine Verbesserung gegenüber Deutschs Algorithmus darstellt.
Deutsch-Jozsa mit Qiskit
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
import numpy as npUm den Deutsch-Jozsa-Algorithmus in Qiskit zu implementieren, definieren wir zunächst eine Funktion dj_query , die einen Quantenschaltkreis erzeugt, der ein Abfragegatter für eine zufällig ausgewählte Funktion implementiert, die das Versprechen für das Deutsch-Jozsa-Problem erfüllt.
Mit einer Wahrscheinlichkeit von 50 % ist die Funktion konstant, und mit einer Veränderung von 50 % ist die Funktion ausgeglichen.
Für jede dieser beiden Möglichkeiten wird die Funktion gleichmäßig aus den Funktionen dieses Typs ausgewählt.
Das Argument ist die Anzahl der Eingabebits der Funktion.
def dj_query(num_qubits):
# Create a circuit implementing for a query gate for a random function
# satisfying the promise for the Deutsch-Jozsa problem.
qc = QuantumCircuit(num_qubits + 1)
if np.random.randint(0, 2):
# Flip output qubit with 50% chance
qc.x(num_qubits)
if np.random.randint(0, 2):
# return constant circuit with 50% chance
return qc
# Choose half the possible input strings
on_states = np.random.choice(
range(2**num_qubits), # numbers to sample from
2**num_qubits // 2, # number of samples
replace=False, # makes sure states are only sampled once
)
def add_cx(qc, bit_string):
for qubit, bit in enumerate(reversed(bit_string)):
if bit == "1":
qc.x(qubit)
return qc
for state in on_states:
qc.barrier() # Barriers are added to help visualize how the functions are created.
qc = add_cx(qc, f"{state:0b}")
qc.mcx(list(range(num_qubits)), num_qubits)
qc = add_cx(qc, f"{state:0b}")
qc.barrier()
return qcWir können die Quantenschaltungsimplementierung des Abfragetors wie üblich mit der Methode draw zeigen.
display(dj_query(3).draw(output="mpl"))Output:
Als Nächstes definieren wir eine Funktion, die den Deutsch-Jozsa-Schaltkreis erzeugt, indem wir eine Quantenschaltkreis-Implementierung eines Abfrage-Gatters als Argument nehmen.
def compile_circuit(function: QuantumCircuit):
# Compiles a circuit for use in the Deutsch-Jozsa algorithm.
n = function.num_qubits - 1
qc = QuantumCircuit(n + 1, n)
qc.x(n)
qc.h(range(n + 1))
qc.compose(function, inplace=True)
qc.h(range(n))
qc.measure(range(n), range(n))
return qcSchließlich wird eine Funktion definiert, die die Deutsch-Jozsa-Schaltung einmal durchläuft.
def dj_algorithm(function: QuantumCircuit):
# Determine if a function is constant or balanced.
qc = compile_circuit(function)
result = AerSimulator().run(qc, shots=1, memory=True).result()
measurements = result.get_memory()
if "1" in measurements[0]:
return "balanced"
return "constant"Wir können unsere Implementierung testen, indem wir eine Funktion zufällig auswählen, die Quantenschaltkreis-Implementierung eines Abfrage-Gatters für diese Funktion anzeigen und dann den Deutsch-Jozsa-Algorithmus für diese Funktion ausführen.
f = dj_query(3)
display(f.draw("mpl"))
display(dj_algorithm(f))Output:
'balanced'
Das Bernstein-Vazirani-Problem
Als Nächstes werden wir ein Problem erörtern, das als Bernstein-Vazirani-Problem bekannt ist. Es wird auch Fourier-Sampling-Problem genannt, obwohl es allgemeinere Formulierungen dieses Problems gibt, die ebenfalls diesen Namen tragen.
Zunächst wollen wir einige Bezeichnungen einführen. Für zwei beliebige Binärzeichenfolgen und der Länge definieren wir
Wir bezeichnen diese Operation als binäres Punktprodukt. Eine andere Möglichkeit der Definition lautet wie folgt.
Beachten Sie, dass es sich hierbei um eine symmetrische Operation handelt, was bedeutet, dass sich das Ergebnis nicht ändert, wenn wir und vertauschen; daher können wir dies tun, wann immer es uns zweckmäßig erscheint. Manchmal ist es hilfreich, sich das binäre Skalarprodukt als die Parität der Bits von an den Stellen vorzustellen, an denen die Zeichenkette ein enthält, oder – was gleichbedeutend ist – als die Parität der Bits von an den Stellen, an denen die Zeichenkette ein enthält.
Mit dieser Notation in der Hand können wir nun das Bernstein-Vazirani-Problem definieren.
Eingabe: eine Funktion \ Versprechen: es existiert eine binäre Zeichenkette für die für alle \ Ausgabe: die Zeichenkette
Wir brauchen eigentlich keinen neuen Quantenalgorithmus für dieses Problem; der Deutsch-Jozsa-Algorithmus löst es. Im Interesse der Klarheit bezeichnen wir die obige Quantenschaltung, die den klassischen Nachbearbeitungsschritt der Berechnung des ODERs nicht enthält, als Deutsch-Jozsa-Schaltung.
Algorithmusanalyse
Um zu analysieren, wie die Deutsch-Jozsa-Schaltung für eine Funktion funktioniert, die das Versprechen für das Bernstein-Vazirani-Problem erfüllt, beginnen wir mit einer kurzen Beobachtung. Unter Verwendung des binären Punktprodukts können wir alternativ die Wirkung von Hadamard-Gattern auf die Standard-Basiszustände von Qubits wie folgt beschreiben.
Ähnlich wie bei der Analyse von Deutschs Algorithmus hängt der Wert für jede ganze Zahl nur davon ab, ob gerade oder ungerade ist.
Bei der Deutsch-Jozsa-Schaltung ist der Zustand der Qubits nach der ersten Schicht von Hadamard-Gattern folgendermaßen
Anschließend wird das Abfragetor ausgeführt, das (durch das Phänomen des Phasenrückschlags) den Zustand in
Unter Verwendung unserer Formel für die Wirkung einer Schicht von Hadamard-Gattern sehen wir, dass die zweite Schicht von Hadamard-Gattern diesen Zustand dann umwandelt in
Nun können wir im Exponenten von „ “ innerhalb der Summe einige Vereinfachungen vornehmen. Uns wird versprochen, dass für eine beliebige Zeichenkette gilt, sodass wir den Zustand wie folgt ausdrücken können:
Da es sich bei und um binäre Werte handelt, können wir die Addition durch die Exklusiv-ODER-Verknüpfung ersetzen - wiederum, weil es für eine ganze Zahl im Exponenten von nur darauf ankommt, ob sie gerade oder ungerade ist. Wenn man die Symmetrie des binären Punktprodukts nutzt, erhält man diesen Ausdruck für den Zustand:
(Der Klarheit halber wurden Klammern hinzugefügt, obwohl sie eigentlich nicht notwendig sind, da es üblich ist, das binäre Punktprodukt mit höherem Vorrang zu behandeln als das Exklusiv-ODER)
An dieser Stelle werden wir die folgende Formel verwenden.
Wir können die Formel durch eine ähnliche Formel für Bits erhalten,
zusammen mit einer Erweiterung des binären Punktprodukts und des bitweisen Exklusiv-ODERs:
Auf diese Weise lässt sich der Zustand der Schaltung unmittelbar vor den Messungen wie folgt ausdrücken:
Der letzte Schritt besteht darin, eine weitere Formel anzuwenden, die für jede Binärzeichenfolge funktioniert.
Hier verwenden wir eine einfache Notation für Zeichenketten, auf die wir im weiteren Verlauf der Lektion noch mehrmals zurückkommen werden: „ “ ist die Zeichenkette, die ausschließlich aus Nullen besteht und die Länge hat.
Eine einfache Möglichkeit, zu belegen, dass diese Formel funktioniert, besteht darin, die beiden Fälle getrennt zu betrachten. Gilt , so gilt für jede Zeichenkette ; somit ist der Wert jedes Terms in der Summe , und wir erhalten , indem wir summieren und durch dividieren. Ist hingegen eines der Bits von gleich , so ist das binäre Skalarprodukt bei genau der Hälfte der möglichen Werte für gleich und bei der anderen Hälfte gleich – denn der Wert des binären Skalarprodukts kehrt sich um (von zu oder von zu ), wenn wir ein beliebiges Bit von an einer Stelle umkehren, an der ein enthält.
Wenn wir nun diese Formel anwenden, um den Zustand der Schaltung vor den Messungen zu vereinfachen, erhalten wir
Da gilt: „ “ genau dann, wenn „ “ gilt. Somit ergeben die Messungen genau die von uns gesuchte Zeichenfolge „ “.
Klassische Schwierigkeit
Während die Deutsch-Jozsa-Schaltung das Bernstein-Vazirani-Problem mit einer einzigen Abfrage löst, muss jeder klassische Abfragealgorithmus mindestens abfragen, um dieses Problem zu lösen.
Dies lässt sich durch ein so genanntes informationstheoretisches Argument begründen, das in diesem Fall sehr einfach ist. Jede klassische Abfrage enthüllt ein einziges Bit an Informationen über die Lösung, und es gibt Bits an Informationen, die aufgedeckt werden müssen - also werden mindestens Abfragen benötigt.
Tatsächlich lässt sich das Bernstein-Vazirani-Problem klassisch lösen, indem man die Funktion für jede der Zeichenfolgen abfragt, die ein einzelnes an jeder möglichen Position enthalten, und für alle anderen Bits, wodurch die Bits von nacheinander ermittelt werden. Daher liegt der Vorteil von Quantenalgorithmen gegenüber klassischen Algorithmen bei diesem Problem darin, dass nur eine Abfrage von erforderlich ist, während bei klassischen Algorithmen Abfragen nötig sind.
Bernstein-Vazirani mit Qiskit
Wir haben die oben beschriebene Deutsch-Jozsa-Schaltung bereits implementiert und werden sie nun nutzen, um das Bernstein-Vazirani-Problem zu lösen. Zunächst definieren wir eine Funktion, die ein Abfrage-Gate für das Bernstein-Vazirani-Problem implementiert, wobei eine beliebige binäre Zeichenkette gegeben ist.
def bv_query(s):
# Create a quantum circuit implementing a query gate for the
# Bernstein-Vazirani problem.
qc = QuantumCircuit(len(s) + 1)
for index, bit in enumerate(reversed(s)):
if bit == "1":
qc.cx(index, len(s))
return qc
display(bv_query("1011").draw(output="mpl"))Output:
Nun können wir eine Funktion erstellen, die die Deutsch-Jozsa-Schaltung auf die Funktion anwendet, indem wir die zuvor definierte Funktion compile_circuit verwenden.
def bv_algorithm(function: QuantumCircuit):
qc = compile_circuit(function)
result = AerSimulator().run(qc, shots=1, memory=True).result()
return result.get_memory()[0]
display(bv_algorithm(bv_query("1011")))Output:
'1011'
Anmerkung zur Nomenklatur
Im Zusammenhang mit dem Bernstein-Vazirani-Problem wird der Deutsch-Jozsa-Algorithmus häufig als "Bernstein-Vazirani-Algorithmus" bezeichnet Dies ist leicht irreführend, denn der Algorithmus ist der Deutsch-Jozsa-Algorithmus, wie Bernstein und Vazirani in ihrer Arbeit sehr deutlich gemacht haben.
Nachdem Bernstein und Vazirani gezeigt hatten, dass der Deutsch-Jozsa-Algorithmus das Bernstein-Vazirani-Problem (wie oben beschrieben) löst, definierten sie ein viel komplizierteres Problem, das so genannte rekursive Fourier-Problem. Dabei handelt es sich um ein hochgradig konstruiertes Problem, bei dem die Lösungen für verschiedene Instanzen des Problems effektiv neue Ebenen des Problems freischalten, die in einer baumartigen Struktur angeordnet sind. Das Bernstein-Vazirani-Problem ist im Grunde nur der Basisfall dieses komplizierteren Problems.
Das rekursive Fourier-Sampling-Problem war das erste bekannte Beispiel für ein Abfrageproblem, bei dem Quantenalgorithmen einen so genannten Super-Polynomialvorteil gegenüber probabilistischen Algorithmen haben und damit den Vorteil von Quantenalgorithmen gegenüber klassischen Algorithmen übertreffen, den der Deutsch-Jozsa-Algorithmus bietet. Intuitiv gesprochen, vergrößert die rekursive Version des Problems den Vorteil von gegenüber der Quantenalgorithmen auf etwas viel Größeres.
Der schwierigste Aspekt der mathematischen Analyse, der diesen Vorteil begründet, ist der Nachweis, dass klassische Abfragealgorithmen das Problem nicht lösen können, ohne viele Abfragen zu machen. Das ist ganz typisch; bei vielen Problemen kann es sehr schwierig sein, kreative klassische Ansätze auszuschließen, die sie effizient lösen.
Simons Problem und der im nächsten Abschnitt beschriebene Algorithmus dafür sind ein viel einfacheres Beispiel für einen superpolynomiellen (und tatsächlich exponentiellen) Vorteil von Quanten- gegenüber klassischen Algorithmen, und aus diesem Grund wird das rekursive Fourier-Sampling-Problem weniger häufig diskutiert. Dennoch ist es ein interessantes Rechenproblem für sich.