Zum Hauptinhalt springen

Praxiseinführung in die DiVincenzo-Kriterien mit Qiskit 2

Einführung

Der Physiker David DiVincenzo beschrieb fünf grundlegende Anforderungen an jede physikalische Implementierung eines Quantencomputers sowie zwei weitere Kriterien für die Quantenkommunikation. In diesem Notebook werden wir jedes DiVincenzo-Kriterium durch praktische Qiskit-Demos erleben. Anstatt tief in die Theorie einzutauchen, erklärt jeder Abschnitt kurz ein Kriterium und bietet dann Code-Übungen mit Qiskit 2. Du wirst Circuits auf Simulatoren und echten IBM Quantum-Geräten ausführen, um jedes Prinzip praktisch zu erkunden.

DiVincenzos fünf Kriterien für die Quantenberechnung:

  1. Ein skalierbares physikalisches System mit gut charakterisierten Qubits.
  2. Fähigkeit zur Initialisierung von Qubits in einem einfachen Referenzzustand (z. B. |00…0〉).
  3. Lange Dekohärenzzeiten (Qubit-Kohärenz deutlich länger als die Gate-Operationszeit).
  4. Ein universeller Satz von Quantum Gates (fähig, beliebige unitäre Operationen durchzuführen).
  5. Qubit-spezifische Messfähigkeit (den Zustand jedes Qubit auslesen).

(DiVincenzo beschrieb außerdem zwei Kriterien für die Quantenkommunikation: die Fähigkeit, stationäre und „fliegende" Qubits ineinander umzuwandeln, und fliegende Qubits zwischen Standorten zuverlässig zu übertragen. Wir behandeln diese in einer empfohlenen Aktivität am Ende dieses Notebooks.)

Jeder der folgenden Abschnitte entspricht einem Kriterium. Wir verwenden Qiskit, um das Konzept mit Code und interaktiven Experimenten zu veranschaulichen, die du ausprobieren kannst. Beispielsweise werden wir sehen, wie die Erhöhung der Qubit-Anzahl und der Circuit-Tiefe die Ergebnisse beeinflusst (Kriterium 1), wie man Qubit-Zustände zurücksetzen und vorbereiten kann (Kriterium 2), wie man Qubits auf Simulatoren im Vergleich zu echten Geräten misst (Kriterium 4), wie Qiskit universelle Gates zusammenstellt (Kriterium 3) und wie endliche Kohärenz (T₁, T₂) Berechnungen beeinflusst (Kriterium 5). Am Ende wirst du ein tieferes Verständnis dafür haben, was jedes DiVincenzo-Kriterium in der Praxis bedeutet und wie Qiskit das Experimentieren damit ermöglicht.

# Added by doQumentation — required packages for this notebook
!pip install -q numpy
# Install necessary packages
!pip install qiskit[visualization] qiskit-ibm-runtime qiskit-aer qiskit_ibm_runtime

1. Kriterium 1 – Skalierbare, gut charakterisierte Qubits

Kriterium 1: „Ein skalierbares physikalisches System mit gut charakterisierten Qubits." Das bedeutet, wir brauchen eine Quantenhardware-Plattform, bei der wir die Anzahl der Qubits erhöhen und sie dennoch zuverlässig steuern können. Die Eigenschaften jedes Qubit (Energieniveaus, Fehlerraten, Konnektivität usw.) sollten gut verstanden sein. Im Wesentlichen wollen wir größere Circuits bauen, ohne dass das System zusammenbricht. In der Praxis akkumulieren sich beim Skalieren der Qubit-Anzahl oder Circuit-Tiefe Fehler und Dekohärenz, weshalb das Demonstrieren von Skalierbarkeit auch bedeutet zu verstehen, wie die Vergrößerung die Leistung beeinflusst.

Ziel der Demo: Qiskit verwenden, um den Effekt der Skalierung eines Circuits (in Qubit-Anzahl oder Gate-Tiefe) auf die Ausgabe-Fidelity zu zeigen. Wir simulieren ein ideales und ein verrauschtes Szenario, um zu sehen, wie ein größeres System oder ein tieferer Circuit der Dekohärenz und Fehlern erliegt.

Zuerst konstruieren wir einen kleinen verschränkten Zustand (GHZ-Zustand) auf 3 Qubits, dann einen größeren auf 5 Qubits, als einfachen Skalierbarkeitstest. Ein GHZ-Zustand mit n Qubits ist 12(0...0+1...1)\frac{1}{\sqrt{2}}(|0...0\rangle + |1...1\rangle). In einer idealen Simulation ergibt das Messen eines n-Qubit-GHZ nur zwei Ergebnisse (alles 0s oder alles 1s) mit gleicher Wahrscheinlichkeit. Wir vergleichen die ideale Ausgabe mit einer verrauschten Ausgabe, wenn wir n oder die Circuit-Tiefe erhöhen.

from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
from qiskit.visualization import plot_histogram
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import SamplerV2 as Sampler

# 3-qubit GHZ circuit
qc3 = QuantumCircuit(3, 3)
qc3.h(0)
qc3.cx(0, 1)
qc3.cx(1, 2)
qc3.measure([0, 1, 2], [0, 1, 2])

# 5-qubit GHZ circuit (scaling up the number of qubits)
qc5 = QuantumCircuit(5, 5)
qc5.h(0)
qc5.cx(0, range(1, 5)) # entangle qubit 0 with all others
qc5.measure(range(5), range(5))

# Transpile for a simulator backend
sim_backend = AerSimulator()
pm = generate_preset_pass_manager(backend=sim_backend, optimization_level=1)
isa_qc3 = pm.run(qc3)
isa_qc5 = pm.run(qc5)

# Run ideal simulations (no noise)
sampler = Sampler(mode=sim_backend)

job3 = sampler.run([isa_qc3], shots=1024)
result3 = job3.result()
counts3 = result3[0].data.c.get_counts()

job5 = sampler.run([isa_qc5], shots=1024)
result5 = job5.result()
counts5 = result5[0].data.c.get_counts()

print("3-qubit GHZ counts (ideal):", counts3)
plot_histogram(counts3, legend=['3-qubit ideal'], figsize=(6,4))
3-qubit GHZ counts (ideal): {'000': 531, '111': 493}

Quantum circuit diagram

print("5-qubit GHZ counts (ideal):", counts5)
plot_histogram(counts5, legend=['5-qubit ideal'], figsize=(6,4))
5-qubit GHZ counts (ideal): {'11111': 535, '00000': 489}

Code output

Erwartetes Ergebnis (Idealfall): Der 3-Qubit-GHZ liefert idealerweise etwa 50% 000 und 50% 111 in den Counts. Der 5-Qubit-GHZ liefert ~50% 00000 und 50% 11111. Keine anderen Bitstrings erscheinen, weil der Zustand idealerweise vollständig kohärent und verschränkt ist. Du solltest zwei hohe Balken im Histogramm für jeden Circuit sehen, die den Alle-Nullen- und Alle-Einsen-Ergebnissen entsprechen.

Als nächstes schauen wir, was in einer verrauschten Umgebung passiert. Wir verwenden die Rauschmodell-Fähigkeiten von Qiskit Aer, um die Fehler eines echten Geräts nachzuahmen. Beispielsweise können wir die Eigenschaften eines IBM-Backends verwenden, um ein Rauschmodell zu erstellen, das Gate-Fehler, endliche Gate-Zeiten, Qubit-Relaxation (T₁), Dephasierung (T₂) und Auslesefehler enthält. Hier verwenden wir ein Fake-Backend, das das IBM Quantum Brisbane-Gerät repräsentiert, um ein Rauschmodell zu erstellen, und führen die GHZ-Circuits damit erneut aus.

Übung 1a: Mit Rauschen simulieren

Vervollständige den Code unten, um die GHZ-Circuits auf einem verrauschten Simulator basierend auf dem FakeBrisbane-Backend zu simulieren. Damit siehst du, wie die Leistung in einer realistischen Rauschumgebung mit zunehmendem System sinkt.

from qiskit_ibm_runtime.fake_provider import FakeBrisbane

# We will reuse the ideal circuits qc3 and qc5 and their results from the previous cell.

# --- YOUR CODE HERE ---

# 1. Create a fake backend for IBM Quantum Brisbane
###brisbane_backend = ...

# 2. Create a noisy AerSimulator from the fake backend's properties
###noisy_sim = ...

# 3. Transpile the circuits for the noisy simulator (this adapts them to the device's specific gates and connectivity)
###pm = ...

###isa_qc3_noisy = ...

###isa_qc5_noisy = ...

# 4. Run the noisy simulations using the Sampler and get the counts
###sampler = ...

###job3 = ...

###result3_noisy = ...

###counts3_noisy = ...

###job5 = ...

###result5_noisy = ...

###counts5_noisy = ...

# --- END YOUR CODE ---

# This part is done for you to print and plot the results:
print("3-qubit GHZ counts (noisy):", counts3_noisy)
plot_histogram(counts3_noisy, legend=['3-qubit noisy'], figsize=(6,4))
print("5-qubit GHZ counts (noisy):", counts5_noisy)
plot_histogram(counts5_noisy, legend=['5-qubit noisy'], figsize=(6,4))

Übung 1b: Auf echtem IBM Quantum-Computer ausführen

Der folgende Code führt die GHZ-Circuits auf einem echten IBM Quantum-Computer aus. Damit siehst du, wie die Leistung auf einem echten Gerät sinkt.

# your_api_key = "deleteThisAndPasteYourAPIKeyHere"
# your_crn = "deleteThisAndPasteYourCRNHere"

# QiskitRuntimeService.save_account(
# channel="ibm_quantum_platform",
# token=your_api_key,
# instance=your_crn,
# name="fallfest-2025",
# )

# Check that the account has been saved properly
# service = QiskitRuntimeService(name="fallfest-2025")
# print(service.saved_accounts())

# We will reuse the ideal circuits qc3 and qc5 and their results from the previous cell.

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService(name="fallfest-2025")
real_backend = service.least_busy(operational=True, simulator=False)
print("Running on " + real_backend.name)

pm = generate_preset_pass_manager(backend=real_backend, optimization_level=1)
isa_qc3r = pm.run(qc3)
isa_qc5r = pm.run(qc5)

sampler = Sampler(mode=real_backend)

job3r = sampler.run([isa_qc3r], shots=1024)
result3r = job3r.result()
counts3r = result3r[0].data.c.get_counts()

job5r = sampler.run([isa_qc5r], shots=1024)
result5r = job5r.result()
counts5r = result5r[0].data.c.get_counts()

print("3-qubit GHZ counts (real):", counts3r)
plot_histogram(counts3r, legend=['3-qubit real'], figsize=(6,4))
print("5-qubit GHZ counts (real):", counts5r)
plot_histogram(counts5r, legend=['5-qubit real'], figsize=(6,4))

Erwartetes Ergebnis (verrauscht vs. ideal): Mit Rauschen, egal ob simuliert oder auf einem echten Gerät, ist der GHZ-Zustand weniger perfekt. Du wirst zusätzliche Ergebnisse jenseits von Alle-0 und Alle-1 sehen. Bei 3 Qubits tritt statt 100% in 000/111 durch Gate-Fehler oder Dekohärenz etwas Wahrscheinlichkeit in andere Bitstrings über (z. B. 001, 010 usw.). Bei 5 Qubits ist der Effekt noch ausgeprägter; der größere Circuit (mehr Qubits und CNOT Gates) akkumuliert mehr Fehler, sodass die Alle-0 und Alle-1 Peaks niedriger sind und viele andere Ergebnisse erscheinen. Dieser Trend veranschaulicht die Herausforderung der Skalierbarkeit: Wenn wir skalieren, wird es ohne Fehlerkorrektur schwieriger, hohe Fidelity zu erhalten.

Erkenntnis: Ein skalierbarer Quantencomputer muss Quantenkorrelationen erhalten, wenn das System wächst. Unsere Beispiele zeigen, wie die Erhöhung der Qubit-Anzahl/Gate-Tiefe dazu führt, dass die Ergebnis-Fidelity bei Rauschen sinkt. Die verbleibenden Kriterien beschäftigen sich damit, diese Qubits gut in Schuss zu halten (geringe Fehler, initialisierbar usw.), wenn wir skalieren.

2. Kriterium 2 – Qubit-Initialisierung

Kriterium 2: „Die Fähigkeit, den Zustand der Qubits in einen einfachen Referenzzustand zu initialisieren, wie z. B. |000…〉." Alle Qubits sollten zuverlässig in einem bekannten Referenzzustand beginnen (typischerweise der Grundzustand |0〉 für jedes Qubit). Die Initialisierung ist wesentlich, damit Algorithmen mit einem sauberen Start beginnen. In der Praxis wird auf IBM Quantum-Geräten jedes Qubit am Anfang jeder Circuit-Ausführung automatisch auf |0〉 zurückgesetzt. Qiskit bietet auch Anweisungen, um Qubits zurückzusetzen oder benutzerdefinierte Zustände während einer Berechnung vorzubereiten.

Ziel der Demo: Zeigen, wie man Qubits in Qiskit initialisiert, sowohl am Anfang als auch mitten im Circuit. Wir demonstrieren die Verwendung der reset-Anweisung und Zustandsvorbereitungsmethoden.

Übung 2: Einen bestimmten Zustand vorbereiten

Vervollständige im Code-Block unten den QuantumCircuit, um den Zustand 10|10\rangle vorzubereiten. Das bedeutet, Qubit 0 sollte im Zustand 0|0\rangle und Qubit 1 im Zustand 1|1\rangle sein. Verwende das geeignete Gate und die geeignete Anweisung, um dies zu erreichen.

from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator

# Create a circuit to initialize qubits to |10> and verify by measurement
qc_init = QuantumCircuit(2, 2)

# --- YOUR CODE HERE ---

# 1. Set qubit 1 to the |1> state

# 2. Explicitly reset qubit 0 to the |0> state

# --- END YOUR CODE ---

qc_init.measure([0, 1], [0, 1])
qc_init.draw('mpl')
# Run the circuit and check the outcome
sim_backend = AerSimulator()
pm = generate_preset_pass_manager(backend=sim_backend, optimization_level=1)
isa_qc_init = pm.run(qc_init)

sampler = Sampler(mode=sim_backend)

job = sampler.run([isa_qc_init], shots=1024)
result = job.result()
counts = result[0].data.c.get_counts()

print("Outcome of |10> state measured in Z-basis:", counts)
plot_histogram(counts)

Du solltest 10 (binär für qubit1=1, qubit0=0) mit 100% Wahrscheinlichkeit aus der Simulation sehen, was bedeutet, dass Qubit 1 erfolgreich in |1〉 und Qubit 0 in |0〉 vorbereitet wurde.

Für eine allgemeinere Zustandsvorbereitung ermöglicht Qiskit die Initialisierung auf beliebige Zustände mit der initialize-Methode. Lass uns zum Beispiel ein Qubit im Zustand +=(0+1)/2|+\rangle = (|0\rangle+|1\rangle)/\sqrt{2}, also einem Superpositionszustand, und ein Qubit-Paar im Bell-Zustand (00+11)/2(|00\rangle+|11\rangle)/\sqrt{2} vorbereiten:

import numpy as np

# Initialize a single qubit in |+> state and measure in Z-basis
qc_plus = QuantumCircuit(1, 1)
state_plus = [1/np.sqrt(2), 1/np.sqrt(2)] # amplitude for |0> and |1>
qc_plus.initialize(state_plus, 0)
qc_plus.measure(0, 0)

# Initialize two qubits in a Bell state manually
qc_bell = QuantumCircuit(2, 2)
bell_state = [1/np.sqrt(2), 0, 0, 1/np.sqrt(2)] # amplitudes for |00>,|01>,|10>,|11>
qc_bell.initialize(bell_state, [0, 1])
qc_bell.measure([0, 1], [0, 1])

# Transpile and run the initialization circuits
isa_qc_plus = pm.run(qc_plus)
job_plus = sampler.run([isa_qc_plus], shots=1024)
result_plus = job_plus.result()
counts_plus = result_plus[0].data.c.get_counts()

print("Outcome of |+> state measured in Z-basis:", counts_plus)

isa_qc_bell = pm.run(qc_bell)
job_bell = sampler.run([isa_qc_bell], shots=1024)
result_bell = job_bell.result()
counts_bell = result_bell[0].data.c.get_counts()

print("Outcome of Bell state measured in Z-basis:", counts_bell)
Outcome of |+> state measured in Z-basis: {'1': 499, '0': 525}
Outcome of Bell state measured in Z-basis: {'00': 508, '11': 516}

Erwartete Ergebnisse: Der einzelne Qubit-Zustand |+〉 liefert beim Messen 0 und 1 mit etwa 50% Wahrscheinlichkeit jeweils. Die Bell-Zustand-Messung sollte etwa 50% 00 und 50% 11 liefern. Wenn du das siehst, bestätigt es, dass unsere Initialisierung auf diese Zustände erfolgreich war.

Mid-Circuit-Initialisierung: Qiskits reset kann mitten in einem Circuit verwendet werden, um ein Qubit im laufenden Betrieb auf |0〉 zu reinitialisieren. Zum Beispiel misst man in Fehlerkorrekturcodes oder iterativen Algorithmen oft ein Qubit und setzt es dann für die Wiederverwendung zurück. Die reset-Operation ist deterministisch; sie verwirft jeden bestehenden Zustand und kühlt das Qubit auf den Grundzustand ab.

Gerätebeispiel: Auf Hardware wie ibmq_brisbane (127 Qubits) oder jedem IBM-Gerät beginnen alle Qubits standardmäßig in |0〉, wenn ein Job ausgeführt wird. Wenn du einen anderen Startzustand benötigst, würdest du am Anfang Gates anwenden (wie wir es mit X getan haben, um |1〉 zu erhalten). Kontinuierliche Re-Initialisierung (für Quantenfehlerkorrektur) ist ein aktives Forschungsthema, weil es eine Herausforderung ist, dies schnell zu tun. Zum Glück ist für den grundlegenden Einsatz die Fähigkeit, frisch in |0…0〉 zu beginnen, verfügbar, und wir haben gezeigt, wie man andere gewünschte Startzustände erreicht.

3. Kriterium 3 – Lange Kohärenzzeit (Dekohärenz vs. Gate-Zeit)

Kriterium 3: „Lange relevante Dekohärenzzeiten, viel länger als die Gate-Operationszeit." Dies betrifft die Notwendigkeit, dass Qubits ihren Quantenzustand lange genug aufrechterhalten, um die notwendigen Operationen durchzuführen. Jedes Qubit hat eine T₁-Zeit (Energierelaxationszeit, wie schnell |1〉 auf |0〉 zerfällt) und eine T₂-Zeit (Dephasierungszeit, wie schnell die relative Phasenkohärenz verloren geht). Damit ein Quantencomputer funktioniert, sollten diese Zeitskalen die Dauer der Gate-Operationen erheblich überschreiten.

Ziel der Demo: Qubit-Kohärenz in Qiskit untersuchen, indem gezeigt wird, wie Dekohärenz die Circuit-Ergebnisse beeinflusst, wenn die Ausführungslänge zunimmt. Wir verwenden ein Fake-Backend mit bekannten T1/T2-Zeiten, um diesen Effekt zu simulieren.

Um den Einfluss endlicher Kohärenz zu demonstrieren, simulieren wir ein T1-Zerfallsexperiment. Wir bereiten ein Qubit im |1〉-Zustand vor, warten eine gewisse Zeit mit einer delay-Anweisung und messen dann. Wir erwarten, dass die Wahrscheinlichkeit, |1〉 zu messen, mit zunehmender Verzögerung abnimmt.

# This part is done for you. We are creating a list of circuits,
# each with a different delay time.

time_delays_ns = [0, 50000, 100000, 150000, 200000, 250000, 300000] # delay durations in ns

decay_expts = []
for delay in time_delays_ns:
qc = QuantumCircuit(1, 1)
qc.x(0) # initialize qubit to |1>
if delay > 0:
qc.delay(delay, 0, unit='ns') # wait 'delay' nanoseconds
qc.measure(0, 0)
decay_expts.append(qc)

decay_expts[1].draw('mpl') # Visualize one of the circuits

Quantum circuit diagram

Übung 3: Ein T1-Zerfallsexperiment simulieren

Verwende nun einen verrauschten Simulator basierend auf FakeVigo (der T1-Zeiten von ~50-100 µs hat), um diese Circuits auszuführen. Der Simulator wendet die T1/T2-Fehler während der delay-Anweisungen automatisch an. Transpiliere die Circuits für dieses Backend und führe sie aus.

from qiskit_ibm_runtime.fake_provider import FakeVigoV2 as FakeVigo
from qiskit_aer import AerSimulator

# --- YOUR CODE HERE ---

# 1. Create a noisy simulator from the FakeVigo backend
###sim_vigo = ...

# 2. Transpile the list of circuits for this simulator
###pm = ...

###isa_decay_expts = ...

# 3. Use the Sampler to run all the transpiled circuits in a single job
###sampler = ...

###job = ...

###result = ...

# --- END YOUR CODE ---

# This part is done for you to analyze and print the results.
for idx, (delay, qc) in enumerate(zip(time_delays_ns, isa_decay_expts)):
counts = result[idx].data.c.get_counts()
p1 = counts.get('1', 0) / 1000 # Assuming 1000 shots
print(f"Delay {delay} ns: P(qubit=1) = {p1:.3f}")

4. Kriterium 4 – Universeller Satz von Quantum Gates

Kriterium 4: „Ein 'universeller' Satz von Quantum Gates." Das bedeutet, unsere Hardware muss es uns ermöglichen, jede Quantenberechnung durch Komposition einer endlichen Menge grundlegender Gates durchzuführen. In der klassischen Informatik ist NAND universell; in der Quantenberechnung gibt es viele Optionen für universelle Gate-Sätze (z. B. {H, T, CNOT} oder die nativen Gates einer bestimmten Maschine). Die IBM-Geräte haben beispielsweise einen Satz nativer Operationen wie beliebige Einzelqubit-Rotationen und CNOTs zwischen bestimmten Qubits, die zusammen universell sind. Die Aufgabe von Qiskit ist es oft, High-Level-Gates in diese Basis-Gates zu kompilieren.

Ziel der Demo: Gate-Universalität veranschaulichen, indem gezeigt wird, wie Qiskit Gates zerlegt. Wir nehmen ein nicht-natives Gate (wie ein 3-Qubit-Toffoli-Gate, CCX) und sehen, wie es in die nativen Basis-Gates des Geräts zerlegt wird. Dies zeigt, dass der bereitgestellte Gate-Satz tatsächlich universell ist – er kann die komplexere Operation erzeugen.

Zuerst sehen wir uns an, was die Basis-Gates für ein typisches IBM-Backend sind. Wir fragen die Konfiguration eines Geräts (oder seiner Fake-Version) ab. Zum Beispiel die Basis-Gates von ibmq_brisbane: Du solltest beobachten, dass die Wahrscheinlichkeit P(qubit=1) mit zunehmender Verzögerungszeit abnimmt und einer exponentiellen Zerfallskurve folgt, die charakteristisch für die T1-Relaxation ist. Dies zeigt direkt, wie endliche Kohärenzzeit zu Rechenfehlern führt, wenn der Circuit zu lange läuft.

Auswirkungen auf Algorithmen: Wenn du einen längeren Algorithmus (mit vielen sequenziellen Gates) versuchst, könnte die Gesamtausführungszeit T2 erreichen oder überschreiten, was dazu führt, dass der Zustand vor dem Ende die Kohärenz verliert. Deshalb sind die Verbesserung der Kohärenzzeiten und die Beschleunigung der Gates zwei der wichtigsten Ziele in der Quantenhardwareforschung.

from qiskit_ibm_runtime.fake_provider import FakeBrisbane
fake_brisbane = FakeBrisbane()
print("Basis gates for ibmq_brisbane:", fake_brisbane.configuration().basis_gates)
Basis gates for ibmq_brisbane: ['ecr', 'id', 'rz', 'sx', 'x']

Dies könnte etwas wie ['id', 'rz', 'sx', 'x', 'ecr'] ausgeben. Das sind die primitiven Operationen, die die Hardware nativ unterstützt (Identity/No-op, RZ-Rotation, sqrt(X)-Gate, X-Gate und Controlled-X). Jedes andere Gate muss aus diesen zusammengesetzt werden. Dieser Satz ist bekanntermaßen universell für die Quantenberechnung (im Wesentlichen Einzelqubit-Rotationen plus ein verschränkendes Zwei-Qubit-Gate bilden einen universellen Satz).

Nimm nun ein Toffoli (CCX)-Gate als Testfall. CCX kippt ein Ziel-Qubit nur, wenn zwei Steuer-Qubits beide 1 sind. Es ist kein natives Gate auf IBM-Hardware. Qiskit bietet eine ccx-Anweisung, aber intern wird es zerlegt.

Übung 4: Ein Toffoli-Gate zerlegen

Vervollständige den Code unten, um einen Circuit mit einem Toffoli (CCX)-Gate zu bauen, und verwende dann Qiskit, um es in die nativen Basis-Gates des FakeBrisbane-Backends zu zerlegen.

from qiskit import QuantumCircuit
from qiskit_ibm_runtime.fake_provider import FakeBrisbane

# The fake_brisbane backend from the previous cell is reused here.

# --- YOUR CODE HERE ---

# 1. Create a circuit that can accommodate a Toffoli gate
###qc_toffoli = ...

# Apply a CCX gate with controls on qubits 0, 1 and target on qubit 2

# 2. Transpile the circuit to the fake Brisbane backend
###pm = ...

###isa_qc_toffoli = ...

# --- END YOUR CODE ---

print("Toffoli circuit before decomposition:")
print(qc_toffoli)

print("\nToffoli circuit after transpiling to Brisbane basis:")
# The .draw() method will now show the decomposed circuit
print(isa_qc_toffoli.draw(fold=120))

In der transpilierten Ausgabe solltest du sehen, dass CCX durch eine Sequenz grundlegenderer Gates wie rz, sx und ecr ersetzt wird. Dies beweist, dass die nativen Gates ausreichen, um den Toffoli auszudrücken.

Universalität in der Praxis: Die obige Übung zeigt, dass ein komplexes 3-Qubit-Gate aus einfacheren aufgebaut wurde. Im Allgemeinen kann jedes Multi-Qubit-Unitar aus 1- und 2-Qubit-Gates zusammengesetzt werden. Der Transpiler ist eine entscheidende Komponente jedes Quantensoftware-Stacks, da er die Lücke zwischen den abstrakten Algorithmen, die wir ausführen möchten, und den physikalischen Operationen, die ein bestimmtes Quantengerät tatsächlich durchführen kann, überbrückt.

Gerätebeispiel: Das ibmq_brisbane-Gerät verwendet die Eagle-Architektur mit den oben gezeigten Basis-Gates. Das bedeutet, dass jeder Algorithmus, der an diese Maschinen gesendet wird, in Sequenzen dieser Operationen umgewandelt wird. Dieses Kriterium betrifft im Wesentlichen die Steuerbarkeit; wir haben genug Kontrollmöglichkeiten, um jede benötigte Operation auf unseren Qubits durchzuführen.

5. Kriterium 5 – Qubit-Messung

Kriterium 5: „Eine Qubit-spezifische Messfähigkeit." Der Zustand jedes Qubit muss messbar sein (typischerweise in der Rechenbasis, |0〉 oder |1〉). Mit anderen Worten, nach dem Ausführen eines Quantum-Circuits müssen wir jedes Qubit als klassisches 0/1-Bit auslesen können. Dieses Kriterium betrifft zuverlässige Detektoren für jedes Qubit und die Fähigkeit auszuwählen, welche Qubits gemessen werden.

Ziel der Demo: Zeigen, wie man in Qiskit auf Simulatoren und echten Geräten Messungen durchführt, und die Unterschiede hervorheben (wie Messrauschen). Wir messen einige Qubits in verschiedenen Zuständen und untersuchen die Ergebnisse. Wir demonstrieren auch, wie Auslesefehler auftreten können, indem wir Simulator- und Hardware-Ergebnisse vergleichen.

Zunächst ein einfaches Messbeispiel:

qc_measure = QuantumCircuit(2, 2)
qc_measure.x(0) # qubit 0 -> |1>, qubit 1 stays |0>
qc_measure.measure([0, 1], [0, 1])
qc_measure.draw('mpl')

Quantum circuit diagram

sim_backend = AerSimulator()
pm = generate_preset_pass_manager(backend=sim_backend, optimization_level=1)
isa_qc_measure = pm.run(qc_measure)
job = sampler.run([isa_qc_measure], shots=1000)
result = job.result()
counts = result[0].data.c.get_counts()

print("Simulator measurement counts:", counts)
Simulator measurement counts: {'01': 1000}

Wir erwarten 1000 Counts von 01 auf dem Simulator. Schauen wir uns nun Messfehler in Aktion an, indem wir ihn simulieren. Wir können unserem Aer-Simulator einen Auslesefehler hinzufügen. Qiskit Aer ermöglicht es uns, einen ReadoutError zu definieren und ihn an Qubits in einem Rauschmodell anzuhängen.

Übung 5: Auslesefehler simulieren

Vervollständige den Code, um ein einfaches Auslesefehlermodell zu definieren, bei dem jedes Qubit eine 2%ige Chance hat, falsch gemessen zu werden (eine 0 wird als 1 gelesen oder eine 1 als 0). Führe dann den Mess-Circuit mit diesem Rauschmodell aus.

from qiskit_aer.noise import NoiseModel, ReadoutError

# --- YOUR CODE HERE ---

# 1. Define a 2% readout error for each single qubit.
# The format is a list of lists of probabilities: [[P(0|0), P(1|0)], [P(0|1), P(1|1)]]
# P(A|B) is the probability of measuring A given the state was |B>.
###ro_error = ...

# 2. Create a new noise model
###noise_model_ro = ...

# 3. Add the readout error to all qubits in the noise model
... # Hint: Use the add_all_qubit_readout_error method

# --- END YOUR CODE ---

sim_backend.set_options(noise_model=noise_model_ro)
pm = generate_preset_pass_manager(backend=sim_backend, optimization_level=1)
isa_qc_measure = pm.run(qc_measure)

# Run the measurement circuit with readout noise
sampler = Sampler(mode=sim_backend)

job = sampler.run([isa_qc_measure], shots=1024)
result = job.result()
counts = result[0].data.c.get_counts()

print("Simulation with 2% readout error:", counts)

Diese simulierte Ausgabe zeigt einige fehlerhafte Counts (wie 11, 00, 10), ähnlich wie sie echte Hardware produzieren könnte, und demonstriert die Auswirkungen unvollkommener Messungen.

Gerätebeispiel: Auf einem echten Gerät wie ibmq_brisbane könnte man denselben Circuit ausführen und würde wahrscheinlich ähnliche, von Null verschiedene Counts für die falschen Ergebnisse sehen. Die Gerätekalibrierungsdaten listen einen Auslesefehler für jedes Qubit auf. Die Fähigkeit, bestimmte Qubits anzusprechen und auszulesen, ist entscheidend, und das Verstehen ihrer Fehlereigenschaften ist der Schlüssel zu aussagekräftigen Ergebnissen. Das Ausführen auf einem echten Gerät wurde in Übung 1b: Auf echtem IBM Quantum-Computer ausführen demonstriert.

Quantenkommunikationskriterien (Fliegende Qubits)

DiVincenzo listete auch zwei Kriterien auf, die speziell für die Quantenkommunikation relevant sind, wichtig beim Aufbau eines vernetzten Quantencomputers:

  1. Fähigkeit zur Umwandlung zwischen stationären und fliegenden Qubits. (Z. B. ein Qubit in einem Prozessor auf ein Photon abbilden, das reisen kann.)
  2. Fähigkeit, fliegende Qubits zuverlässig zwischen Standorten zu übertragen. (Z. B. ein Photon-Qubit durch eine Faser zu senden, ohne Quanteninformation zu verlieren.)

Dies geht über die Standard-Qiskit-Nutzung hinaus, da Qiskit hauptsächlich mit stationären Qubits auf einem Chip arbeitet. Wir können jedoch das Konzept dieser Kriterien mit einem einfachen Beispiel veranschaulichen: Quantenteleportation. Die Teleportation zeigt, wie man den Zustand eines stationären Qubit in Information umwandelt, die von einem verschränkten Paar (dem „fliegenden" Teil) und klassischer Kommunikation getragen wird, die dann verwendet wird, um den Zustand auf einem anderen stationären Qubit anderswo zu rekonstruieren.

Das Qiskit in Classrooms-Modul Quantum Teleportation von Dr. Katie McCormick führt dich durch eines der faszinierendsten Protokolle der Quanteninformation: die Quantenteleportation, bei der ein Quantenzustand (ein Qubit) von Alice zu Bob gesendet wird, indem Verschränkung und nur zwei klassische Bits verwendet werden. Du lernst Schritt für Schritt das vollständige Teleportationsverfahren kennen – wie man das verschränkte Bell-Paar vorbereitet, eine Bell-Basis-Messung auf Alices Seite durchführt, klassische Ergebnisse überträgt und das korrekte Quantum Gate auf Bobs Qubit anwendet, um den ursprünglichen Zustand perfekt wiederherzustellen. Dabei erkundest du, warum die Teleportation der Information eines Qubit weder das No-Cloning-Theorem verletzt noch die Lichtgeschwindigkeit überschreitet. Durch praktische Übungen mit IBM Quantum-Hardware oder Simulatoren erhältst du ein praktisches Verständnis von Messung, Verschränkung und Feed-Forward-Steuerung in der Praxis.

Indem du die Quantenteleportation beherrschst, verstehst du, wie man Quanteninformation zwischen verschiedenen Knoten kodiert, überträgt und wiederherstellt – und legst damit den Grundstein für Quantennetzwerke, Repeater-Systeme, sichere Kommunikationsschemata und skalierbare modulare Quantencomputer. Bezug zu Kriterien 6 & 7: In einem echten Quantennetzwerk würde das gemeinsame verschränkte Paar durch das Verteilen von „fliegenden" Qubits (wie Photonen) zwischen den Standorten von Alice und Bob erstellt (Kriterium 7: zuverlässige Übertragung). Das Teleportationsprotokoll selbst dient dann als Möglichkeit, Alices stationären Qubit-Zustand auf ihre Hälfte des verschränkten Paares abzubilden und ihn damit effektiv an Bob zu „senden" (Kriterium 6: Umwandlung). Qiskit ermöglicht es uns, die Logik des Protokolls perfekt zu simulieren und bietet ein konzeptionelles Modell dafür, wie diese Kriterien in Kommunikationsarchitekturen erfüllt werden.

Fazit und Zusammenfassung

Wir haben eine Reihe von Code-fokussierten Übungen entworfen, um die DiVincenzo-Kriterien mit Qiskit zu veranschaulichen. Durch diese praxisorientierten Beispiele hast du erkundet, wie eine echte Quantencomputing-Plattform jede Anforderung erfüllt:

  • Skalierbarkeit: Circuits auf mehr Qubits aufbauen und Rauschskalierung verstehen.
  • Initialisierung: Resets und Zustandsvorbereitung verwenden, um Berechnungen zuverlässig in bekannten Zuständen zu starten.
  • Universelle Gates: Komplexe Operationen in die Basis-Gates einer Maschine transpilieren und so beweisen, dass wir jede Berechnung durchführen können.
  • Messung: Qubits auslesen und mit realistischen Auslesefehlern umgehen.
  • Kohärenz: Den Effekt endlicher T₁, T₂ auf die Algorithmus-Fidelity sehen und die Notwendigkeit, dass Operationen relativ zur Dekohärenz schnell sein müssen.

Der Vollständigkeit halber haben wir auch Aspekte der Quantenkommunikation über das Qiskit in Classrooms-Modul Quantum Teleportation angesprochen und die letzten beiden Kriterien (fliegende Qubits) verknüpft.

Abschließend lohnt es sich anzumerken, wie diese Kriterien in einem echten Quantencomputer wie dem von IBM zusammenwirken. Ein Gerät wie ibmq_brisbane hat 127 supraleitende Qubits (Kriterium 1), die jeweils in |0〉 beginnen (Kriterium 2), mit kalibriertem Gate-Satz und Compilern für Universalität (Kriterium 4), Mikrowellen-Ausleseresonatoren für jedes Qubit (Kriterium 5) und Kohärenzzeiten in der Größenordnung von Hunderten von Mikrosekunden im Vergleich zu Nanosekunden-Operationen (Kriterium 3). Für Quantennetzwerk-Experimente erforschen IBM und andere die Mikrowellen-zu-optische Transduktion für fliegende Qubits und die Verschränkung entfernter Qubits (Kriterien 6 & 7); das sind aktive Forschungsbereiche.

Indem du die Übungen in diesem Notebook abgeschlossen hast, hast du nicht nur die Definitionen der DiVincenzo-Kriterien gesehen, sondern sie durch Code erlebt; du hast ein tieferes Verständnis dafür entwickelt, was jede Anforderung für echte Quantenhardware und Algorithmen bedeutet. Du kannst diese Experimente gerne erweitern – viel Spaß beim Quantencomputing!