Dein erstes Quantenexperiment
Einführung​
Im folgenden Video führt dich Olivia Lanes durch den Inhalt dieser Lektion. Alternativ kannst du das YouTube-Video zu dieser Lektion in einem separaten Fenster öffnen.
Bis jetzt hast du deinen ersten Quantum Circuit ausgeführt und die Grundlagen des Quantencomputings gelernt: wie Quantenzustände dargestellt werden, wie Gates auf diese Zustände wirken und wie Quantenmerkmale wie Superposition und Verschränkung dabei eine Rolle spielen. Jetzt ist es Zeit, all das in die Praxis umzusetzen und dein erstes Problem auf einem Quantencomputer zu lösen.
Die breitere Landschaft quantengeeigneter Probleme werden wir in einer späteren Lektion erkunden. Für jetzt konzentrieren wir uns auf ein Problem aus dem Bereich der Natursimulation: die Verwendung eines Quantencomputers als saubereren, besser kontrollierbaren Ersatz für ein natürliches Quantensystem. Das war tatsächlich die erste Anwendung, die Richard Feynman in den 1980er Jahren für Quantencomputer vorgesehen hat. Wie er es treffend formulierte: „Die Natur ist nicht klassisch, verdammt nochmal, und wenn du eine Simulation der Natur machen willst, musst du sie quantenmechanisch machen …"
In dieser Lektion folgen wir diesem Prinzip, um die Wechselwirkung zwischen zwei Spins zu simulieren, die du dir als winzige Magnete vorstellen kannst. Abhängig vom Vorzeichen ihrer Wechselwirkung bevorzugen sie es, sich auszurichten und in dieselbe Richtung zu zeigen, oder sich anti-auszurichten und in entgegengesetzte Richtungen zu zeigen. Wir konzentrieren uns auf den letzteren Fall, weil er oft zu interessanterem — und herausforderndererem — Verhalten führt. Wenn wir dieses kleine Zwei-Qubit-System erst einmal verstanden haben, zeigen wir, wie sich dieselben Ideen skalieren lassen und Quantencomputer ihre exponentielle Skalierung beim Simulieren großer Spin-Systeme nutzen können.
Zwei wechselwirkende Magnete​
Für dieses Problem verwenden wir zwei Qubits, eines für jeden Spin in unserem Modell. Jeder Spin kann nach oben zeigen (Qubit-Zustand ), nach unten zeigen (Qubit-Zustand ) oder sich in einer Superposition der beiden Zustände befinden.
Wenn die Spins eine antiferromagnetische Wechselwirkung haben, bedeutet das, dass sie sich anti-ausrichten wollen: Wenn einer nach oben zeigt, möchte der andere nach unten zeigen, und umgekehrt.
Angenommen, es gibt auch ein Magnetfeld, das von links nach rechts in unserem System zeigt. Da dieses Feld quer zur üblichen Auf-Ab-Richtung der Spins zeigt, wird es als transversales Feld bezeichnet. Dieses Feld kann Spins umklappen, was dazu führt, dass die niedrigste Energiekonfiguration eine bestimmte Superposition aus Auf-Ab-Spin-Anordnungen ist, anstatt ein einzelnes bestimmtes Spin-Muster.
Wir können all diese Effekte mit einem mathematischen Objekt namens Hamiltonian beschreiben. Der Hamiltonian gibt uns die Energie des Systems für eine gegebene Anordnung von Spins:
wobei ein Koeffizient ist, der die Stärke der Wechselwirkung zwischen Spins steuert, und ein Koeffizient für die Stärke des externen Magnetfelds ist. belohnt oder bestraft die Spins, je nachdem ob sie ausgerichtet oder anti-ausgerichtet sind, und und repräsentieren den Spin-Flip-Effekt des Magnetfelds.
In der Physik neigen Systeme dazu, sich in den Zustand mit der niedrigst möglichen Energie einzustellen, den sogenannten Grundzustand. Diesen niedrigsten Energiezustand zu finden ist ein häufiges Problem, erfordert jedoch Optimierungstechniken, die den Rahmen dieser Lektion überschreiten.
Stattdessen werden wir eine einfachere Frage stellen: Wenn wir die Spins in einem bestimmten Zustand präparieren, wie hoch ist die Energie dieses Zustands?
Um dies zu beantworten, werden wir:
- Die Spins in einem Zustand unserer Wahl präparieren
- Die Energie dieses Zustands mit dem obigen Hamiltonian messen
Dies ist genau die Art von Berechnung, die in größeren Quantenalgorithmen vorkommt, wie z. B. Variationsalgorithmen, die du in späteren Kursen erkunden kannst.
Qiskit-Implementierung​
Bevor wir mit dem Schreiben von Code beginnen, brauchen wir etwas Kontext. Wenn wir einen Quantum Circuit ausführen, beenden wir immer mit dem Messen der Qubits. Aber es gibt zwei verschiedene Arten von Fragen, die wir über das Ergebnis dieser Messung stellen können: Manchmal wollen wir einfach nur wissen, in welchem Zustand sich das Qubit befindet. Zu anderen Zeiten wollen wir wissen: Was ist, angesichts des Quantenzustands, der Wert einer physikalischen Größe, wie z. B. Energie?
In Qiskit werden diese zwei Arten von Fragen von zwei verschiedenen Werkzeugen behandelt, sogenannten Primitiven.
Sampler beantwortet die erste Art von Frage. Er führt den Circuit viele Male aus und sagt uns, wie oft wir jedes mögliche Ergebnis messen, wie 00, 01, 10 oder 11. Das Ergebnis ist ein Histogramm, das die Wahrscheinlichkeit jedes Messergebnisses anzeigt.
Estimator beantwortet die zweite Art von Frage. Anstatt uns ein Histogramm zu geben, kombiniert er viele Messungen im Hintergrund, um eine einzelne Zahl zu berechnen, z. B. die Energie des Zustands gemäß einem Hamiltonian, den wir angeben.
Um dir zu helfen zu verstehen, wann und warum wir jedes dieser Werkzeuge verwenden würden, werden wir zwei vollständige Arbeitsabläufe (sogenannte „Qiskit-Patterns") durchgehen, die auf dasselbe Zwei-Qubit-System angewendet werden.
Qiskit-Patterns-Arbeitsablauf​
Der Qiskit-Patterns-Arbeitsablauf ist ein allgemeines Framework, das wir zur Lösung von Quantenproblemen mit Qiskit verwenden. Er unterteilt eine Quantencomputing-Aufgabe in vier Schritte:
- Das Problem auf ein Modell abbilden, das durch Quantum Circuits dargestellt werden kann
- Den Circuit für die Ausführung auf einem bestimmten Backend optimieren
- Den optimierten Circuit auf dem ausgewählten Backend ausführen
- Die rohen Messdaten nachverarbeiten
Experiment 1: Sampler verwenden, um den Zustand zu messen​
Abbilden​
Im Allgemeinen ist der Abbildungsschritt der Ort, an dem wir herausfinden, wie wir ein reales Problem in Qubits, Operatoren und Messungen übersetzen. In vielen Anwendungen ist das der schwierigste und aufwändigste Teil des Arbeitsablaufs — selbst einfache Fragen wie „Was repräsentiert jedes Qubit?" haben nicht immer einfache Antworten.
In diesem Experiment ist die Abbildung jedoch bewusst einfach gehalten. Jeder physikalische Freiheitsgrad wird direkt auf ein einzelnes Qubit abgebildet. Aufgrund dieser Eins-zu-eins-Entsprechung reduziert sich der Abbildungsschritt auf die Auswahl des Quantenzustands, den wir präparieren wollen, und das Schreiben eines Circuits, der diesen Zustand präpariert und misst.
Hier werden wir einen verschränkten Bell-Zustand präparieren, ähnlich dem, den wir in der allerersten Lektion dieses Kurses erstellt haben:
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-runtime
# Import Qiskit primitives
from qiskit import QuantumCircuit
# Make state
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.x(1)
qc.z(0)
# Measure state
qc.measure_all()
# Draw circuit
qc.draw("mpl")
Optimieren​
Bevor wir unseren Circuit auf einem Quantencomputer ausführen (oder auf einem Simulator, falls du deine kostenlosen Minuten auf echten Quantencomputern für den Monat aufgebraucht hast), müssen wir ihn für die Ausführung vorbereiten. Dieser Schritt wird als Optimierung bezeichnet. (Hinweis: Diese Verwendung des Begriffs „Optimierung" kann verwirrend sein. Im Quantencomputing bezieht sich der Begriff Optimierungsprobleme auf eine bestimmte Klasse von Problemen. Hier verwenden wir Optimierung, um einen erforderlichen Vorbereitungsschritt zu beschreiben, den jeder Quantum Circuit durchläuft, bevor er effizient auf Hardware ausgeführt werden kann.)
Während der Optimierung:
- Wählen wir das Backend aus — entweder einen echten Quantencomputer oder einen Simulator.
- Weisen wir die Qubits unseres Circuits physikalischen Qubits auf dem Gerät zu.
- Schreiben wir den Circuit so um, dass er nur die Gates verwendet, die der Quantencomputer tatsächlich ausführen kann.
- Implementieren wir optional Fehlerminimirungs- und -unterdrückungstechniken, um die Auswirkungen von Rauschen zu reduzieren.
In Qiskit wird dies automatisch vom Transpiler gehandhabt. Sobald du dein Backend auswählst, erledigt der Transpiler alle Arbeit, um deinen Circuit für die Ausführung vorzubereiten, sodass du die Gates oder Qubit-Zuweisungen nicht manuell anpassen musst. Der Transpiler bietet auch verschiedene Optimierungsstufen, die bei Bedarf helfen können, Fehler zu reduzieren. Die Optimierung wird in Phasen durchgeführt, die „Passes" genannt werden. Diese Optimierung wird daher im folgenden Code vom pass_manager übernommen. Um mehr über Fehler und Fehlerminimierung zu erfahren, schau dir Olivia Lanes' Kurs Quantum Computing in Practice an.
# Load the Qiskit Runtime service
from qiskit_ibm_runtime import QiskitRuntimeService
## Load the Qiskit Runtime service
# QiskitRuntimeService.save_account(
# channel="ibm_quantum_platform",
# token="YOUR_TOKEN_HERE",
# overwrite=True,
# set_as_default=True,
# )
# service = QiskitRuntimeService(channel="ibm_quantum_platform")
# Or load saved credentials
service = QiskitRuntimeService()
# Use the least busy backend, or uncomment the loading of a specific backend like "ibm_brisbane".
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
# backend = service.backend("ibm_brisbane")
print(backend.name)
ibm_fez
# Transpile the circuit and optimize for running on the quantum computer selected
# Step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
qc_isa.draw("mpl")
Ausführen​
Jetzt sind wir bereit zur Ausführung! Wir laden den Sampler und senden den Job dann an das Backend.
# Load the Runtime primitive and session
from qiskit_ibm_runtime import SamplerV2 as Sampler
sampler = Sampler(mode=backend)
Oder, wenn du einen Simulator verwendest, kannst du stattdessen diese Zelle auskommentieren und ausführen:
## Load the backend sampler
# from qiskit.primitives import BackendSamplerV2
## Load the Aer simulator and generate a noise model based on the currently-selected backend.
# from qiskit_aer import AerSimulator
# from qiskit_aer.noise import NoiseModel
# noise_model = NoiseModel.from_backend(backend)
## Define a simulator using Aer, and use it in Sampler.
# backend_sim = AerSimulator(noise_model=noise_model)
# sampler_sim = BackendSamplerV2(backend=backend_sim)
## Alternatively, load a fake backend with generic properties and define a simulator.
## backend_gen = GenericBackendV2(num_qubits=18)
## sampler_gen = BackendSamplerV2(backend=backend_gen)
job = sampler.run([qc_isa], shots=100)
# job = sampler_sim.run([qc_isa]) # uncomment if you want to run on a simulator
res = job.result()
counts = res[0].data.meas.get_counts()
Nachverarbeitung​
from qiskit.visualization import plot_histogram
print("counts = ", counts)
plot_histogram(counts)
counts = {'10': 49, '01': 50, '11': 1}
Wir sehen, dass die Mehrheit der Counts entweder in 01 oder 10 liegt, was bedeutet: Wenn ein Qubit als 0 gemessen wurde, war das andere 1, und umgekehrt. Das ist konsistent mit dem Bell-Zustand , den wir präpariert haben.
Experiment 2: Estimator verwenden, um die Energie zu messen​
Nachdem wir gesehen haben, wie man einen Quantenzustand abtastet, verwenden wir nun den Estimator, um die Energie unseres Bell-Zustands zu berechnen.
Abbilden​
Zur Erinnerung: Die Energie des Systems wird durch die Wechselwirkung zwischen den Spins () und dem externen Magnetfeld () bestimmt, wie vom Hamiltonian erfasst:
Jeder Term im Hamiltonian sagt uns, wie eine bestimmte Kombination von Spins zur Energie beiträgt. In Qiskit können wir diese Terme als Pauli-Operatoren darstellen, die einfach Labels für einfache Aktionen auf Qubits sind:
- wirkt mit einem auf beide Qubits.
- wirkt mit auf Qubit 0.
- wirkt mit auf Qubit 1.
Ein SparsePauliOp in Qiskit ist eine Möglichkeit, eine Liste dieser Pauli-Operatoren zusammen mit ihren numerischen Koeffizienten zu speichern. Diese Pauli-Operatoren sind die Observablen, die wir vom Quantencomputer messen lassen wollen — die Größen, die uns etwas über das System verraten. Mit Estimator können wir den Durchschnittswert jeder Observable in unserem Zustand berechnen und sie entsprechend den Koeffizienten im Hamiltonian kombinieren, um die Gesamtenergie zu erhalten.
# Import Qiskit primitives
from qiskit.quantum_info import SparsePauliOp
# Parameters
J = 1.0 # antiferromagnetic coupling (J<0)
hx = -0.5 # transverse field strength
# 1. Define the Hamiltonian H = J Z1 Z2 + hx (X1 + X2)
obs = SparsePauliOp.from_list([("ZZ", J), ("XI", hx), ("IX", hx)])
# Make state
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.x(1)
qc.z(0)
<qiskit.circuit.instructionset.InstructionSet at 0x1387ed630>
Beachte, dass wir die Zeile qc.measure_all() in unserem Code weggelassen haben. Das liegt daran, dass wir beim Estimator nicht angeben müssen, wo im Circuit gemessen werden soll. Wir sagen ihm einfach, welche Observablen wir schätzen wollen, und Qiskit kümmert sich um die Messungen im Hintergrund.
Optimieren​
Der Optimierungsschritt verläuft wie zuvor, mit dem Zusatz, dass wir sicherstellen müssen, dass unsere Observablen ebenfalls in einer Weise geschrieben sind, die der Quantencomputer verstehen kann.
# Transpile the circuit and optimize for running on the quantum computer selected
# Step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs_isa = obs.apply_layout(layout=qc_isa.layout)
qc_isa.draw("mpl")
Ausführen​
Im Ausführungsschritt laden wir Estimator und senden dann den Circuit zusammen mit der Liste der Observablen, die wir schätzen lassen wollen, an den Quantencomputer.
# Load the Runtime primitive and session
from qiskit_ibm_runtime import EstimatorV2 as Estimator
estimator = Estimator(mode=backend)
# Load the backend sampler
# noise_model = NoiseModel.from_backend(backend)
# Use Aer simulator in Estimator
# estimator_sim = BackendEstimatorV2(backend=backend_sim)
# Alternatively, load a fake backend with generic properties and define a simulator.
# backend_gen = GenericBackendV2(num_qubits=18)
# estimator_gen = BackendEstimatorV2(backend=backend_gen)
pubs = [(qc_isa, obs_isa)]
job = estimator.run([[qc_isa, obs_isa]])
res = job.result()
# Uncomment lines below to run the job on the Aer simulator with noise model from real backend
# job = estimator_sim.run([[qc_isa,obs_isa]])
# res=job.result()
Nachverarbeitung​
Schließlich drucken wir im Nachverarbeitungsschritt einfach die Energie aus, die der Estimator im Hintergrund berechnet hat.
print(res[0].data.evs)
-0.9934112021453058
Das ist die Energie unseres Zustands!
Fazit​
In dieser Lektion haben wir gelernt, wie man einen einfachen Zwei-Qubit-Quantenzustand präpariert, der zwei wechselwirkende Spins darstellt. Wir haben gesehen, wie man Sampler verwendet, um die Verteilung der Messergebnisse zu beobachten, und wie man Estimator verwendet, um die Energie des Zustands gemäß dem Hamiltonian zu berechnen. Dabei haben wir gesehen, wie der Hamiltonian die Wechselwirkungen zwischen Spins und die Effekte eines externen Feldes kodiert, und wie verschiedene Zustände unterschiedliche Energien haben können.
Erweiterung auf viele Spins​
Bisher haben wir uns nur zwei Spins angeschaut, was einfach genug ist, um es von Hand zu analysieren. In realen physikalischen Systemen, wie in einem Magneten oder einem anderen komplexen Material, gibt es oft viele wechselwirkende Spins. Wenn die Anzahl der Spins zunimmt, wird der Hamiltonian komplexer und die Suche nach dem niedrigsten Energiezustand wird viel schwieriger. Hier können Quantencomputer helfen: indem sie verschiedene Zustände präparieren und ihre Energien schätzen, können sie niedrigenergetische Konfigurationen für große Systeme effizienter erkunden als klassische Computer.
Eine natürliche Erweiterung dieses Experiments wäre, die Anzahl der Qubits zu erhöhen, um mehr Spins zu repräsentieren, und die Art und Weise, wie die Spins präpariert werden, anzupassen, um den niedrigsten Energiezustand zu finden. Dieser Ansatz ist das Wesen variationaler Methoden, über die du im Kurs Variational Quantum Algorithms mehr erfahren kannst.
Es gibt auch andere Quantenansätze zur Untersuchung von Grundzustandsenergien, die über Variationsmethoden hinausgehen. Diese Methoden werden hier nicht behandelt, werden aber im Kurs Quantum Diagonalization Algorithms vorgestellt, falls du dich dafür interessierst.
Lernziel​
Geh zurück zum Anfang von Experiment 2 und probiere es mit einem anderen Superpositionszustand. Kannst du einen Zustand mit noch niedrigerer Energie als den von uns verwendeten finden?