Zum Hauptinhalt springen

Nishimori-Phasenübergang

Geschätzter Aufwand: 3 Minuten auf einem Heron-r2-Prozessor (HINWEIS: Dies ist nur eine Schätzung. Deine Laufzeit kann abweichen.)

Lernziele

Nach dem Durcharbeiten dieses Tutorials sollten Benutzer folgende Ergebnisse erwarten:

  • Den Nishimori-Phasenübergang verstehen und wie er sich als das Auftreten langreichweitiger Verschränkung im Random-Bond-Ising-Modell zeigt.
  • Das Protokoll zur Erzeugung von Verschränkung durch Messung (GEM) auf Quantenhardware mit Mid-Circuit-Messungen und Schaltkreisen konstanter Tiefe implementieren.
  • Den Übergang durch Extraktion der Zwei-Punkt-Korrelation und der normierten Varianz der Magnetisierung aus experimentellen Daten charakterisieren.

Voraussetzungen

Wir empfehlen, die folgenden Themen vor diesem Tutorial zu kennen:

Hintergrund

Dieses Tutorial zeigt, wie man einen Nishimori-Phasenübergang auf einem Quantenprozessor realisiert. Das Experiment wurde ursprünglich in Realizing the Nishimori transition across the error threshold for constant-depth quantum circuits beschrieben.

Der Nishimori-Phasenübergang bezeichnet den Übergang zwischen kurzreichweitig und langreichweitig geordneten Phasen im Random-Bond-Ising-Modell. Auf einem Quantencomputer manifestiert sich die langreichweitig geordnete Phase als ein Zustand, in dem Qubits über das gesamte Gerät verschränkt sind. Dieser hochverschränkte Zustand wird mit dem Protokoll zur Erzeugung von Verschränkung durch Messung (GEM) präpariert. Durch den Einsatz von Mid-Circuit-Messungen kann das GEM-Protokoll Qubits über das gesamte Gerät hinweg mit Schaltkreisen konstanter Tiefe verschränken. Dieses Tutorial verwendet die Implementierung des GEM-Protokolls aus dem Softwarepaket GEM Suite.

Anforderungen

Stelle vor Beginn dieses Tutorials sicher, dass Folgendes installiert ist:

  • Qiskit SDK v1.0 oder neuer, mit Unterstützung für Visualisierung
  • Qiskit Runtime v0.22 oder neuer (pip install qiskit-ibm-runtime)
  • Qiskit Aer v0.14 oder neuer (pip install qiskit-aer)
  • GEM Suite (pip install gem-suite)

Einrichtung

# Added by doQumentation — required packages for this notebook
!pip install -q gem-suite matplotlib qiskit qiskit-aer qiskit-ibm-runtime
import matplotlib.pyplot as plt
import warnings

from collections import defaultdict

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_aer import AerSimulator

from qiskit.transpiler import generate_preset_pass_manager

from gem_suite import PlaquetteLattice
from gem_suite.experiments import GemExperiment

Kleines Simulator-Beispiel

In diesem Abschnitt wird der vollständige Ablauf auf dem rauschfreien AerSimulator durchgegangen. Das Plaquette-Gitter wird auf eine einzige Plaquette (12 Qubits) beschränkt, damit die Simulation klein und schnell bleibt und trotzdem jeden Teil des GEM-Protokolls abdeckt: Mid-Circuit-Messung, den RZZR_{ZZ}-Winkeldurchlauf, Dekodierung und die normierte-Varianz-Analyse. Derselbe Ablauf wird später auf mehrere Plaquettes und das vollständige Gitter auf echter Hardware skaliert.

Schritt 1: Klassische Eingaben auf ein Quantenproblem abbilden

Das GEM-Protokoll arbeitet auf einem Quantenprozessor, dessen Qubit-Konnektivität durch ein Gitter beschrieben wird. Aktuelle IBM Quantum®-Prozessoren verwenden das Heavy-Hex-Gitter. Die Qubits des Prozessors werden anhand der Einheitszelle des Gitters, die sie besetzen, in Plaquettes gruppiert. Da ein Qubit in mehr als einer Einheitszelle vorkommen kann, sind die Plaquettes nicht disjunkt. Auf dem Heavy-Hex-Gitter enthält eine Plaquette 12 Qubits. Die Plaquettes bilden ihrerseits auch ein Gitter, wobei zwei Plaquettes verbunden sind, wenn sie Qubits teilen. Auf dem Heavy-Hex-Gitter teilen benachbarte Plaquettes jeweils 3 Qubits.

Im Softwarepaket GEM Suite ist die grundlegende Klasse zur Implementierung des GEM-Protokolls PlaquetteLattice, die das Gitter der Plaquettes repräsentiert (das sich vom Heavy-Hex-Gitter unterscheidet). Eine PlaquetteLattice kann aus einer Qubit-Kopplungsmap initialisiert werden. Derzeit werden nur Heavy-Hex-Kopplungsmaps unterstützt.

Die folgende Code-Zelle initialisiert ein Plaquette-Gitter aus der Kopplungsmap einer Quantenverarbeitungseinheit (QPU). Das Plaquette-Gitter umfasst nicht immer die gesamte Hardware. Beispielsweise hat ibm_torino insgesamt 133 Qubits, aber das größte Plaquette-Gitter, das auf das Gerät passt, verwendet nur 125 davon und umfasst 18 Plaquettes; ibm_pittsburgh (156 Qubits) passt ähnlich 144 Qubits in 21 Plaquettes. Dasselbe Muster gilt für andere Heavy-Hex-QPUs mit unterschiedlichen Qubit-Zahlen.

# QiskitRuntimeService.save_account(channel="ibm_quantum", token="<YOUR_API_KEY>", overwrite=True,
# set_as_default=True)
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
)
aer_backend = AerSimulator.from_backend(backend)
plaquette_lattice = PlaquetteLattice.from_coupling_map(backend.coupling_map)

print(f"Number of qubits in backend: {backend.num_qubits}")
print(
f"Number of qubits in plaquette lattice: {len(list(plaquette_lattice.qubits()))}"
)
print(f"Number of plaquettes: {len(list(plaquette_lattice.plaquettes()))}")

Du kannst das Plaquette-Gitter visualisieren, indem du ein Diagramm seiner Graphdarstellung erzeugst. Im Diagramm werden die Plaquettes durch beschriftete Sechsecke dargestellt, und zwei Plaquettes sind durch eine Kante verbunden, wenn sie Qubits teilen.

plaquette_lattice.draw_plaquettes()

Output of the previous code cell

Mit der Methode plaquettes kannst du Informationen über einzelne Plaquettes abrufen, z. B. welche Qubits sie enthalten.

# Get a list of the plaquettes
plaquettes = list(plaquette_lattice.plaquettes())
# Display information about plaquette 0
plaquettes[0]
PyPlaquette(index=0, qubits=[3, 4, 5, 6, 7, 16, 17, 23, 24, 25, 26, 27], neighbors=[4, 3, 1])

Du kannst auch ein Diagramm der zugrunde liegenden Qubits erzeugen, die das Plaquette-Gitter bilden.

plaquette_lattice.draw_qubits()

Output of the previous code cell

Neben den Qubit-Bezeichnungen und den Kanten, die anzeigen, welche Qubits verbunden sind, enthält das Diagramm drei weitere Informationen, die für das GEM-Protokoll relevant sind:

  • Jedes Qubit ist entweder schattiert (grau) oder nicht schattiert. Die schattierten Qubits sind „Site"-Qubits, die die Gitterplätze des Ising-Modells repräsentieren, und die nicht schattierten Qubits sind „Bond"-Qubits, die zur Vermittlung von Wechselwirkungen zwischen den Site-Qubits dienen.
  • Jedes Site-Qubit ist entweder mit (A) oder (B) beschriftet und gibt damit eine von zwei Rollen an, die ein Site-Qubit im GEM-Protokoll übernehmen kann (die Rollen werden später erläutert).
  • Jede Kante ist in einer von sechs Farben eingefärbt, wodurch die Kanten in sechs Gruppen aufgeteilt werden. Diese Aufteilung bestimmt, wie Zwei-Qubit-Gates parallelisiert werden können, sowie verschiedene Scheduling-Muster, die auf einem verrauschten Quantenprozessor wahrscheinlich unterschiedlich viel Fehler verursachen. Da Kanten innerhalb einer Gruppe disjunkt sind, kann eine Schicht von Zwei-Qubit-Gates gleichzeitig auf diesen Kanten angewendet werden. Tatsächlich lassen sich die sechs Farben in drei Gruppen zu je zwei Farben aufteilen, sodass die Vereinigung jeder Gruppe von zwei Farben immer noch disjunkt ist. Daher werden nur drei Schichten von Zwei-Qubit-Gates benötigt, um jede Kante zu aktivieren. Es gibt 12 Möglichkeiten, die sechs Farben so aufzuteilen, und jede solche Aufteilung ergibt ein anderes 3-Schicht-Gate-Schedule.

Nachdem du ein Plaquette-Gitter erstellt hast, besteht der nächste Schritt darin, ein GemExperiment-Objekt zu initialisieren, dem sowohl das Plaquette-Gitter als auch das Backend übergeben werden, auf dem du das Experiment ausführen möchtest. Die Klasse GemExperiment verwaltet die eigentliche Implementierung des GEM-Protokolls, einschließlich der Erzeugung von Schaltkreisen, des Einreichens von Jobs und der Analyse der Daten. Die folgende Code-Zelle initialisiert die Experiment-Klasse und schränkt das Plaquette-Gitter dabei auf eine einzige Plaquette (12 Qubits) ein, damit die Simulation klein und schnell bleibt. Das vollständige Plaquette-Gitter wird später beim Skalieren auf echte Hardware verwendet.

# Filter the plaquette lattice down to a single plaquette (12 qubits)
# so the AerSimulator run stays fast. The full lattice is used later
# in the large-scale hardware example.
gem_exp = GemExperiment(plaquette_lattice.filter([9]), backend=aer_backend)

# visualize the plaquette lattice after filtering
plaquette_lattice.filter([9]).draw_qubits()

Output of the previous code cell

Ein GEM-Protokoll-Schaltkreis wird mithilfe der folgenden Schritte aufgebaut:

  1. Bereite den Zustand +|+\rangle für alle Qubits vor, indem du auf jedes Qubit ein Hadamard-Gate anwendest.
  2. Wende ein RZZR_{ZZ}-Gate zwischen jedem Paar verbundener Qubits an. Dies kann mit drei Gate-Schichten erreicht werden. Jedes RZZR_{ZZ}-Gate wirkt auf ein Site-Qubit und ein Bond-Qubit. Wenn das Site-Qubit mit (B) beschriftet ist, ist der Winkel auf π2\frac{\pi}{2} festgelegt. Wenn das Site-Qubit mit (A) beschriftet ist, kann der Winkel variieren und so verschiedene Schaltkreise erzeugen. Standardmäßig ist der Winkelbereich auf 21 gleichmäßig verteilte Punkte zwischen 00 und π2\frac{\pi}{2} (einschließlich) eingestellt.
  3. Miss jedes Bond-Qubit in der Pauli-XX-Basis. Da Qubits in der Pauli-ZZ-Basis gemessen werden, kann dies erreicht werden, indem vor der Messung des Qubits ein Hadamard-Gate angewendet wird.

Beachte, dass das in der Einleitung dieses Tutorials zitierte Paper eine andere Konvention für den RZZR_{ZZ}-Winkel verwendet, die sich von der in diesem Tutorial verwendeten Konvention um einen Faktor 2 unterscheidet.

In Schritt 3 werden nur die Bond-Qubits gemessen. Um zu verstehen, in welchem Zustand die Site-Qubits verbleiben, ist es hilfreich, den Fall zu betrachten, dass der in Schritt 2 auf Site-Qubits (A) angewendete RZZR_{ZZ}-Winkel gleich π2\frac{\pi}{2} ist. In diesem Fall befinden sich die Site-Qubits in einem hochverschränkten Zustand ähnlich dem GHZ-Zustand,

GHZ=0000+1111.\lvert \text{GHZ} \rangle = \lvert 00 \cdots 00 \rangle + \lvert 11 \cdots 11 \rangle.

Aufgrund der Zufälligkeit der Messergebnisse kann der tatsächliche Zustand der Site-Qubits ein anderer Zustand mit langreichweitiger Ordnung sein, beispielsweise 00110+11001\lvert 00110 \rangle + \lvert 11001 \rangle. Der GHZ-Zustand kann jedoch durch eine Dekodierungsoperation auf Basis der Messergebnisse wiederhergestellt werden. Wenn der RZZR_{ZZ}-Winkel von π2\frac{\pi}{2} heruntergeregelt wird, kann die langreichweitige Ordnung noch bis zu einem kritischen Winkel wiederhergestellt werden, der ohne Rauschen bei ungefähr 0,3π0{,}3 \pi liegt. Unterhalb dieses Winkels weist der resultierende Zustand keine langreichweitige Verschränkung mehr auf. Dieser Übergang zwischen dem Vorhandensein und dem Fehlen langreichweitiger Ordnung ist der Nishimori-Phasenübergang.

In der obigen Beschreibung wurden die Site-Qubits ungemessen gelassen, und die Dekodierungsoperation kann durch Anwenden von Quantengattern durchgeführt werden. Im Experiment, wie es in der GEM Suite implementiert ist, werden die Site-Qubits tatsächlich gemessen, und die Dekodierungsoperation wird in einem klassischen Nachverarbeitungsschritt angewendet.

In der obigen Beschreibung kann die Dekodierungsoperation durch Anwenden von Quantengattern auf die Site-Qubits durchgeführt werden, um den Quantenzustand wiederherzustellen. Wenn das Ziel jedoch darin besteht, den Zustand sofort zu messen – beispielsweise zu Charakterisierungszwecken –, dann kannst du die Site-Qubits zusammen mit den Bond-Qubits messen und die Dekodierungsoperation in einem klassischen Nachverarbeitungsschritt anwenden.

Zusätzlich zur Abhängigkeit vom RZZR_{ZZ}-Winkel in Schritt 2, der standardmäßig über 21 Werte durchläuft, hängt der GEM-Protokoll-Schaltkreis auch vom verwendeten Scheduling-Muster ab, mit dem die drei Schichten von RZZR_{ZZ}-Gates implementiert werden. Wie bereits erwähnt, gibt es 12 solcher Scheduling-Muster. Daher beträgt die Gesamtanzahl der Schaltkreise im Experiment 21×12=25221 \times 12 = 252.

Die Schaltkreise des Experiments können mit der Methode circuits der Klasse GemExperiment erzeugt werden.

circuits = gem_exp.circuits()
print(f"Total number of circuits: {len(circuits)}")
Total number of circuits: 252

Für die Zwecke dieses Tutorials reicht es aus, nur ein einziges Scheduling-Muster zu betrachten. Die folgende Code-Zelle schränkt das Experiment auf das erste Scheduling-Muster ein. Dadurch hat das Experiment nur noch 21 Schaltkreise, einen für jeden durchlaufenen RZZR_{ZZ}-Winkel.

# Restrict experiment to the first scheduling pattern
gem_exp.set_experiment_options(schedule_idx=0)

# There are less circuits now
circuits = gem_exp.circuits()
print(f"Total number of circuits: {len(circuits)}")

# Print the RZZ angles swept over
print(f"RZZ angles:\n{gem_exp.parameters()}")
Total number of circuits: 21
RZZ angles:
[0. 0.07853982 0.15707963 0.23561945 0.31415927 0.39269908
0.4712389 0.54977871 0.62831853 0.70685835 0.78539816 0.86393798
0.9424778 1.02101761 1.09955743 1.17809725 1.25663706 1.33517688
1.41371669 1.49225651 1.57079633]

Die folgende Code-Zelle zeichnet ein Diagramm des Schaltkreises mit Index 5. Um die Größe des Diagramms zu reduzieren, werden die Messgatter am Ende des Schaltkreises entfernt.

# Get the circuit at index 5
circuit = circuits[5]
# Remove the final measurements to ease visualization
circuit.remove_final_measurements()
# Draw the circuit
circuit.draw("mpl", fold=-1, scale=0.5)

Output of the previous code cell

Schritt 2: Problem für die Ausführung auf Quantenhardware optimieren

Das Transpilieren von Quantenschaltkreisen für die Ausführung auf Hardware umfasst typischerweise eine Reihe von Phasen. Die Phasen, die den größten Rechenaufwand verursachen, sind in der Regel die Auswahl des Qubit-Layouts, das Routing der Zwei-Qubit-Gates gemäß der Qubit-Konnektivität der Hardware sowie die Optimierung des Schaltkreises zur Minimierung der Gate-Anzahl und -Tiefe. Im GEM-Protokoll sind die Layout- und Routing-Phasen nicht erforderlich, da die Hardware-Konnektivität bereits in den Entwurf des Protokolls eingeflossen ist. Die Schaltkreise haben bereits ein Qubit-Layout, und die Zwei-Qubit-Gates sind bereits auf native Verbindungen abgebildet. Darüber hinaus sollte, um die Struktur des Schaltkreises bei Variation des RZZR_{ZZ}-Winkels zu erhalten, nur eine sehr grundlegende Schaltkreisoptimierung durchgeführt werden.

Die Klasse GemExperiment transpiliert Schaltkreise bei der Ausführung des Experiments transparent. Die Layout- und Routing-Phasen sind standardmäßig bereits so überschrieben, dass sie nichts tun, und die Schaltkreisoptimierung wird auf einem Niveau durchgeführt, das nur Einzelqubit-Gates optimiert. Du kannst jedoch zusätzliche Optionen mit der Methode set_transpile_options überschreiben oder übergeben. Zur Veranschaulichung transpiliert die folgende Code-Zelle den zuvor angezeigten Schaltkreis manuell und zeichnet den transpilierten Schaltkreis.

# Demonstrate setting transpile options
gem_exp.set_transpile_options(
optimization_level=1 # This is the default optimization level
)
pass_manager = generate_preset_pass_manager(
backend=aer_backend,
initial_layout=list(gem_exp.physical_qubits),
**dict(gem_exp.transpile_options),
)
transpiled = pass_manager.run(circuit)
transpiled.draw("mpl", idle_wires=False, fold=-1, scale=0.5)

Output of the previous code cell

Schritt 3: Ausführung mit Qiskit-Primitiven

Um die GEM-Protokoll-Schaltkreise auf der Hardware auszuführen, rufe die Methode run des GemExperiment-Objekts auf. Du kannst die Anzahl der Shots angeben, die du aus jedem Schaltkreis sampeln möchtest. Die Methode run gibt ein ExperimentData-Objekt zurück, das du in einer Variablen speichern solltest. Beachte, dass die Methode run Jobs nur einreicht, ohne auf deren Abschluss zu warten – es handelt sich also um einen nicht-blockierenden Aufruf.

exp_data = gem_exp.run(shots=10_000)

Um auf die Ergebnisse zu warten, rufe die Methode block_for_results des ExperimentData-Objekts auf. Dieser Aufruf lässt den Interpreter warten, bis die Jobs abgeschlossen sind.

# The noiseless AerSimulator produces zero-variance UFloat objects in the
# analysis, which triggers a harmless warning from the `uncertainties`
# library. Suppress it so the output stays clean.
with warnings.catch_warnings():
warnings.filterwarnings(
"ignore", message="Using UFloat objects with std_dev==0"
)
exp_data.block_for_results()
exp_data
ExperimentData(GemExperiment, 90bf2a90-f729-4c4e-a6da-664aecb11039, job_ids=['04a7c405-47fd-46ca-aa4b-aaf7e339cfbe'], metadata=<5 items>, figure_names=['two_point_correlation.svg', 'normalized_variance.svg', 'plaquette_ops.svg', 'bond_ops.svg'])

Schritt 4: Nachverarbeitung und Ausgabe im gewünschten klassischen Format

Bei einem RZZR_{ZZ}-Winkel von π2\frac{\pi}{2} wäre der dekodierte Zustand ohne Rauschen der GHZ-Zustand. Die langreichweitige Ordnung des GHZ-Zustands kann durch Darstellung der Magnetisierung der gemessenen Bitstrings visualisiert werden. Die Magnetisierung MM ist definiert als die Summe der Einzel-Qubit-Pauli-ZZ-Operatoren,

M=j=1NZj,M = \sum_{j=1}^N Z_j,

wobei NN die Anzahl der Site-Qubits ist. Ihr Wert für einen Bitstring ist gleich der Differenz zwischen der Anzahl der Nullen und der Anzahl der Einsen. Die Messung des GHZ-Zustands liefert mit gleicher Wahrscheinlichkeit den Zustand aus lauter Nullen oder den Zustand aus lauter Einsen, sodass die Magnetisierung halb der Zeit +N+N und die andere Hälfte der Zeit N-N wäre. Bei Fehlern durch Rauschen würden zwar auch andere Werte auftreten, aber wenn das Rauschen nicht zu groß ist, wäre die Verteilung immer noch nahe bei +N+N und N-N konzentriert.

Für die rohen Bitstrings vor der Dekodierung wäre die Verteilung der Magnetisierung äquivalent zu der gleichmäßig zufälliger Bitstrings, ohne Rauschen.

Die folgende Code-Zelle stellt die Magnetisierung der rohen Bitstrings und der dekodierten Bitstrings beim RZZR_{ZZ}-Winkel von π2\frac{\pi}{2} dar.

def magnetization_distribution(
counts_dict: dict[str, int],
) -> dict[str, float]:
"""Compute magnetization distribution from counts dictionary."""
# Construct dictionary from magnetization to count
mag_dist = defaultdict(float)
for bitstring, count in counts_dict.items():
mag = bitstring.count("0") - bitstring.count("1")
mag_dist[mag] += count
# Normalize
shots = sum(counts_dict.values())
for mag in mag_dist:
mag_dist[mag] /= shots
return mag_dist

# Get counts dictionaries with and without decoding
data = exp_data.data()
# Get the last data point, which is at the angle for the GHZ state
raw_counts = data[-1]["counts"]
# Without decoding
site_indices = [
i for i, q in enumerate(gem_exp.plaquettes.qubits()) if q.role == "Site"
]
site_raw_counts = defaultdict(int)
for key, val in raw_counts.items():
site_str = "".join(key[-1 - i] for i in site_indices)
site_raw_counts[site_str] += val
# With decoding
_, site_decoded_counts = gem_exp.plaquettes.decode_outcomes(
raw_counts, return_counts=True
)

# Compute magnetization distribution
raw_magnetization = magnetization_distribution(site_raw_counts)
decoded_magnetization = magnetization_distribution(site_decoded_counts)

# Plot
plt.bar(*zip(*raw_magnetization.items()), label="raw")
plt.bar(*zip(*decoded_magnetization.items()), label="decoded", width=0.3)
plt.legend()
plt.xlabel("Magnetization")
plt.ylabel("Frequency")
plt.title("Magnetization distribution with and without decoding")
Text(0.5, 1.0, 'Magnetization distribution with and without decoding')

Output of the previous code cell

Um die langreichweitige Ordnung strenger zu charakterisieren, kannst du die mittlere Zwei-Punkt-Korrelation ff betrachten, definiert als

f=1N2(M2M2).f = \frac{1}{N^2} \left(\langle M^2 \rangle - \langle M \rangle ^2\right).

Ein höherer Wert zeigt einen höheren Grad an Verschränkung an. Die Klasse GemExperiment berechnet diesen Wert für die dekodierten Bitstrings automatisch als Teil der Verarbeitung der Experimentdaten. Sie speichert eine Abbildung, die über die Methode figure der Experimentdaten-Klasse zugänglich ist. In diesem Fall heißt die Abbildung two_point_correlation.

exp_data.figure("two_point_correlation")

Output of the previous code cell

Um den kritischen Punkt des Nishimori-Phasenübergangs zu bestimmen, kannst du die normierte Varianz von M2/NM^2 / N betrachten, definiert als

g=1N3(M4M22),g = \frac{1}{N^3} \left(\langle M^4 \rangle - \langle M^2 \rangle^2\right),

die das Ausmaß der Fluktuationen in der quadratischen Magnetisierung quantifiziert. Dieser Wert ist am kritischen Punkt des Nishimori-Phasenübergangs maximal. Ohne Rauschen liegt der kritische Punkt bei ungefähr 0,3π0{,}3 \pi. In Gegenwart von Rauschen verschiebt sich der kritische Punkt nach oben, aber der Phasenübergang ist noch beobachtbar, solange der kritische Punkt unterhalb von 0,5π0{,}5 \pi liegt.

exp_data.figure("normalized_variance")

Output of the previous code cell

Hardware-Beispiel im großen Maßstab

Nachdem du das Protokoll auf einem Simulator validiert hast, kannst du das Experiment nun skalieren und auf dem im Abschnitt Einrichtung ausgewählten echten Quantenhardware-Backend ausführen. Dieses Beispiel verwendet zwei größere Problemgrößen:

  • Sechs Plaquettes (~49 Qubits): ein mittelgroßer Durchlauf, der bereits die Rechtsverschiebung des kritischen Punkts unter Hardware-Rauschen zeigt.
  • Das vollständige Plaquette-Gitter: alle Plaquettes, die die Heavy-Hex-Topologie des Geräts unterstützt (beispielsweise 18 Plaquettes / 125 Qubits auf ibm_torino oder 21 Plaquettes / 144 Qubits auf ibm_pittsburgh), wobei Qubits über das gesamte Gerät mit Schaltkreisen konstanter Tiefe verschränkt werden.

Die einzelne Code-Zelle unten ist in sich abgeschlossen: Sie baut das Plaquette-Gitter aus der Kopplungsmap des Backends auf und führt beide Experimente aus, sodass dieser Abschnitt nach den Einrichtungs-Zellen ausgeführt werden kann, ohne zuvor den Abschnitt im kleinen Maßstab zu durchlaufen.

# -------------------------Step 1-------------------------
# Initialize the runtime service, pick a real quantum hardware backend,
# and build the plaquette lattice from its coupling map. This is repeated
# from the small-scale example so this cell can run standalone after the
# Setup section. The full plaquette lattice is the "large-scale" target;
# a six-plaquette subset (range(3, 9)) is also used to show an intermediate
# scaling step.
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
)
plaquette_lattice = PlaquetteLattice.from_coupling_map(backend.coupling_map)

# Build a GemExperiment for the full plaquette lattice and one for the
# six-plaquette subset, each restricted to a single scheduling pattern so
# the experiment has one circuit per RZZ angle (21 circuits total).
gem_exp_full = GemExperiment(plaquette_lattice, backend=backend)
gem_exp_full.set_experiment_options(schedule_idx=0)
gem_exp_6 = GemExperiment(
plaquette_lattice.filter(range(3, 9)), backend=backend
)
gem_exp_6.set_experiment_options(schedule_idx=0)

circuits = gem_exp_full.circuits()
print(f"Total number of circuits (full lattice): {len(circuits)}")

# -------------------------Step 2-------------------------
# GemExperiment transpiles internally for the target backend: the layout
# and routing stages are overridden because the plaquette lattice already
# matches the hardware connectivity, and optimization is restricted so the
# RZZ angle structure is preserved. The code below manually transpiles one
# circuit from the six-plaquette experiment with the same settings this
# experiment will use, and draws it for inspection. (The full-lattice
# transpiled circuit has too many qubits to visualize cleanly, so the
# six-plaquette circuit is used here as a representative example.)
gem_exp_6.set_transpile_options(optimization_level=1)
circuits_6 = gem_exp_6.circuits()
pass_manager = generate_preset_pass_manager(
backend=backend,
initial_layout=list(gem_exp_6.physical_qubits),
**dict(gem_exp_6.transpile_options),
)
transpiled = pass_manager.run(circuits_6[5])
display(transpiled.draw("mpl", idle_wires=False, fold=-1, scale=0.5))

# -------------------------Step 3-------------------------
# Run both problem sizes on real hardware:
# 1. Six plaquettes (~49 qubits) — an intermediate scale-up.
# 2. The full plaquette lattice — every plaquette the device supports.
exp_data_6 = gem_exp_6.run(shots=10_000, job_tags=["TUT_NPT"])
exp_data_full = gem_exp_full.run(shots=10_000, job_tags=["TUT_NPT"])
exp_data_6.block_for_results()
exp_data_full.block_for_results()

# -------------------------Step 4-------------------------
# Plot the normalized variance at each scale. The peak marks the critical
# point of the Nishimori transition; as the system grows, hardware noise
# shifts the peak rightward.
display(exp_data_6.figure("normalized_variance"))
exp_data_full.figure("normalized_variance")
Total number of circuits (full lattice): 21

Output of the previous code cell

Output of the previous code cell

Output of the previous code cell

Beachte, dass die Kurven der normierten Varianz bei den größeren Problemgrößen je nach Rauschpegel des verwendeten Backends möglicherweise keinen deutlichen Peak im durchlaufenen Winkelbereich zeigen. In den obigen Durchläufen wurde der Peak ganz an 0,5π0{,}5 \pi, den rechten Rand des Durchlaufs, geschoben (die Analyse meldet critical_angle = 0.5000 sowohl für die Sechs-Plaquette- als auch für die Vollgitter-Durchläufe). Das bedeutet, dass das Hardware-Rauschen den kritischen Punkt an (oder knapp über) die Grenze des physikalisch sinnvollen Winkelbereichs des Protokolls verschoben hat, sodass der Übergang am Rand dessen liegt, was dieser Durchlauf auflösen kann.

Fazit

In diesem Tutorial hast du einen Nishimori-Phasenübergang auf einem Quantenprozessor mithilfe des GEM-Protokolls realisiert. Die Kenngrößen, die du bei der Nachverarbeitung untersucht hast — insbesondere die Zwei-Punkt-Korrelation und die normierte Varianz — dienen als Benchmarks für die Fähigkeit des Geräts, langreichweitig verschränkte Zustände zu erzeugen. Diese Benchmarks erweitern den Nutzen des GEM-Protokolls über die Untersuchung interessanter Physik hinaus. Im Rahmen des Protokolls hast du Qubits über das gesamte Gerät hinweg mit Schaltkreisen konstanter Tiefe verschränkt. Diese Leistung ist nur dank der Verwendung von Mid-Circuit-Messungen durch das Protokoll möglich. In diesem Experiment wurde der verschränkte Zustand sofort gemessen, aber erkunde gerne weiter, indem du diesen Zustand in weiterer Quantenverarbeitung einsetzt.

Nächste Schritte

Empfehlungen

Falls dir diese Arbeit interessant erscheint, könnten dich die folgenden Materialien interessieren:

Referenzen

[1] E. H. Chen, G.-Y. Zhu, R. Verresen, A. Seif, E. Bäumer, D. Layden, N. Tantivasadakarn, G. Zhu, S. Sheldon, A. Vishwanath, S. Trebst, A. Kandala. Realizing the Nishimori transition across the error threshold for constant-depth quantum circuits. arXiv:2309.02863 (2023).

[2] GEM Suite Softwarepaket.