Nishimori Phasenübergang
Dauer: Ungefähr 3 Minuten uffm Heron r2 Prozessor (ACHTUNG: Das is nur ne Schätzung. Deine Laufzeit kann annerscht sein.)
Hintergrund
Das Tutorial zeigt, wie mr'n Nishimori Phasenübergang uffm IBM® Quantenprozessor durchführt. Das Experiment wurde ursprünglich beschrieben in Realizing the Nishimori transition across the error threshold for constant-depth quantum circuits.
Der Nishimori Phasenübergang bezieht sich uff den Übergang zwischn kurz- un langstreckengeordneten Phasen im Zufalls-Bindungs-Ising-Modell. Uffm Quantencomputer zeigt sich de langstreckengeordnete Phase als'n Zustand, wo de Qubits übern ganzen Gerät verschrängt sin. Dieser hochgradig verschränkte Zustand wird mitm generation of entanglement by measurement (GEM) Protokoll erzeugt. Durchs Verwenden von Messungen innerhalb vom Schaltkreis kann das GEM-Protokoll Qubits übern ganzen Gerät verschränken mit Schaltkreisen von nur konstanter Tiefe. Hier verwenden mr de Implementierung vom GEM-Protokoll ausm GEM Suite Software-Paket.
Voraussetzungen
Bevor de mitm Tutorial anfängst, sorge dafür, dass de das installiert hast:
- Qiskit SDK v1.0 oder neuer, mit Visualisierung Unterstützung
- Qiskit Runtime v0.22 oder neuer (
pip install qiskit-ibm-runtime) - GEM Suite (
pip install gem-suite)
Vorbereitung
# Added by doQumentation — installs packages not in the Binder environment
!pip install -q gem-suite
import matplotlib.pyplot as plt
from collections import defaultdict
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.transpiler import generate_preset_pass_manager
from gem_suite import PlaquetteLattice
from gem_suite.experiments import GemExperiment
Schritt 1: Klassische Eingaben uff'n Quantenproblem abbilden
Das GEM-Protokoll arbeitet uffm Quantenprozessor mit Qubit-Konnektivität, de durchn Gitter beschrieben wird. De heutigen IBM Quantenprozessoren verwenden das Heavy-Hex-Gitter. De Qubits vom Prozessor werden in Plaketten einjedeilt, je nachdem in welcher Einheitszelle vom Gitter se liegen. Weil'n Qubit in mehr als eener Einheitszelle vorkommen kann, sin de Plaketten nich disjunkt. Uffm Heavy-Hex-Gitter hat ne Plakette 12 Qubits. De Plaketten selbst bilden ooch'n Gitter, wo zwei Plaketten verbunden sin, wennse irgendwelche Qubits teilen. Uffm Heavy-Hex-Gitter teilen benachbarte Plaketten 3 Qubits.
Im GEM Suite Software-Paket is de Grundklasse für de Implementierung vom GEM-Protokoll PlaquetteLattice, was das Gitter von de Plaketten darstellt (was annerscht is wie das Heavy-Hex-Gitter). Ne PlaquetteLattice kann ausner Qubit Coupling Map initialisiert wern. Momentan wern nur Heavy-Hex Coupling Maps unterstützt.
De nächste Code-Zelle initialisiert'n Plaketten-Gitter ausner Coupling Map vonm IBM Quantenprozessor. Das Plaketten-Gitter umfasst nich immer de ganze Hardware. Zum Beispiel hat ibm_torino 133 Qubits insgesamt, aber das größte Plaketten-Gitter, was uffs Gerät passt, braucht nur 125 davon un umfasst insgesamt 18 Plaketten. Ähnliches kann mr ooch bei IBM Quantum® Geräten mit annern Qubit-Zahlen beobachten.
# QiskitRuntimeService.save_account(channel="ibm_quantum", token="<YOUR_API_KEYN>", overwrite=True, set_as_default=True)
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
)
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()))}")
Number of qubits in backend: 133
Number of qubits in plaquette lattice: 125
Number of plaquettes: 18
De kannst das Plaketten-Gitter visualisieren, indem de'n Diagramm von seiner Graph-Darstellung erzeugst. Im Diagramm wern de Plaketten als beschriftete Sechsecke dargestellt, un zwei Plaketten sin durchne Kante verbunden, wennse Qubits teilen.
plaquette_lattice.draw_plaquettes()
De kannst Informationen über einzelne Plaketten abrufen, wie zum Beispiel de Qubits, de se enthalten, mitder plaquettes Methode.
# Get a list of the plaquettes
plaquettes = list(plaquette_lattice.plaquettes())
# Display information about plaquette 0
plaquettes[0]
PyPlaquette(index=0, qubits=[0, 1, 2, 3, 4, 15, 16, 19, 20, 21, 22, 23], neighbors=[3, 1])
De kannst ooch'n Diagramm von de zugrunde liegenden Qubits erzeugen, de das Plaketten-Gitter bilden.
plaquette_lattice.draw_qubits()

Zusätzlich zu de Qubit-Bezeichnungen un de Kanten, de zeigen, welche Qubits verbunden sin, enthält das Diagramm drei weitere Informationen, de fürs GEM-Protokoll relevant sin:
- Jedes Qubit is entweder schattiert (grau) oder nich schattiert. De schattierten Qubits sin "Site"-Qubits, de de Plätze vom Ising-Modell darstellen, un de nich schattierten Qubits sin "Bond"-Qubits, de verwendet wern, um Interaktionen zwischn de Site-Qubits zu vermitteln.
- Jedes Site-Qubit is entweder (A) oder (B) bezeichnet, was eene von zwei Rollen anzeigt, de'n Site-Qubit im GEM-Protokoll spielen kann (de Rollen wern später erklärt).
- Jede Kante is mit eener von sechs Farben eingefärbt, was de Kanten in sechs Gruppen aufdeilt. Diese Aufdeilung bestimmt, wie Zwei-Qubit-Gatter parallelisiert wern können, sowie verschiedene Zeitpläne, de wohrscheinlich verschiedene Fehlerraten uffm rauschenden Quantenprozessor verursachen. Weil de Kanten inner Gruppe disjunkt sin, kann ne Schicht von Zwei-Qubit-Gattern uff dene Kanten gleichzeitig angelegt wern. Tatsächlich kann mr de sechs Farben in drei Gruppen von zwei Farben aufdeilen, so dass de Vereinigung von jeder Gruppe von zwei Farben immer noch disjunkt is. Deswegen wern nur drei Schichten von Zwei-Qubit-Gattern gebraucht, um jede Kante zu aktivieren. Es jibt 12 Wege, de sechs Farben so uffzudeilen, un jede solche Aufdeilung liefert'n annern 3-Schichten-Gatter-Zeitplan.
Nachdem de'n Plaketten-Gitter erzeugt hast, is der nächste Schritt, 'n GemExperiment Objekt zu initialisieren, wo de sowohl das Plaketten-Gitter als ooch das Backend reinjibbst, uff dem de das Experiment durchführen willst. De GemExperiment Klasse verwaltet de eigentliche Implementierung vom GEM-Protokoll, was ooch Schaltkreise erzeugt, Jobs einreicht un Daten analysiert. De nächste Code-Zelle initialisiert de Experiment-Klasse un beschränkt das Plaketten-Gitter uff nur zwei von de Plaketten (21 Qubits), um de Größe vom Experiment zu reduzieren un sicherzustellen, dass das Rauschen in der Hardware nich das Signal überwältigt.
gem_exp = GemExperiment(plaquette_lattice.filter([9, 12]), backend=backend)
# visualize the plaquette lattice after filtering
plaquette_lattice.filter([9, 12]).draw_qubits()

'n GEM-Protokoll-Schaltkreis wird mit dene Schritten gebaut:
- Erzeuge den all- Zustand, indem'n Hadamard-Gatter uff jedes Qubit angelegt wird.
- Lege'n Gatter zwischn jedem Paar von verbundenen Qubits an. Das kann mr mit 3 Schichten von Gattern erreichen. Jedes Gatter wirkt uff'n Site-Qubit un'n Bond-Qubit. Wenn das Site-Qubit (B) bezeichnet is, dann is der Winkel fest uff gesetzt. Wenn das Site-Qubit (A) bezeichnet is, dann darf der Winkel variieren, was verschiedene Schaltkreise liefert. Standardmäßig is der Bereich von Winkeln uff 21 gleichmäßig verteilte Punkte zwischn un , inklusive, gesetzt.
- Messe jedes Bond-Qubit in der Pauli Basis. Weil Qubits in der Pauli Basis gemessen wern, kann mr das machen, indem'n Hadamard-Gatter vor der Messung angelegt wird.
Beachte, dass das Paper, was in der Einleitung von diesem Tutorial zitiert wird, ne annere Konvention für'n Winkel verwendet, de sich durchn Faktor von 2 von der Konvention in diesem Tutorial unterscheidet.
In Schritt 3 wern nur de Bond-Qubits gemessen. Um zu verstehn, in welchem Zustand de Site-Qubits bleiben, is es hilfreich, den Fall zu betrachten, dass der Winkel, der in Schritt 2 uff Site-Qubits (A) angelegt wird, gleich is. In diesem Fall bleiben de Site-Qubits in'm hochgradig verschränkten Zustand, ähnlich wie beim GHZ-Zustand,
Wejen der Zufälligkeit in de Messungserjebnissen könnte der eigentliche Zustand von de Site-Qubits'n annerer Zustand mit Langstreckenordnung sein, zum Beispiel, . Aber der GHZ-Zustand kann wiederhergestellt wern, indem ne Dekodierungsoperation basierend uff de Messungserjebnissen angelegt wird. Wenn der Winkel von runterjedreht wird, kann de Langstreckenordnung noch immer wiederhergestellt wern bis zu'm kritischen Winkel, der in Abwesenheit von Rauschen ungefähr is. Unter diesem Winkel zeigt der Zustand, der erzeugt wird, keene Langstreckenverschränkung mehr. Dieser Übergang zwischn der Anwesenheit un Abwesenheit von Langstreckenordnung is der Nishimori Phasenübergang.
In der Beschreibung hier oben wurden de Site-Qubits nich gemessen, un de Dekodierungsoperation kann durchjeführt wern, indem Quantengatter angelegt wern. Im Experiment, wie's in der GEM Suite implementiert is, was diesem Tutorial folgt, wern de Site-Qubits tatsächlich gemessen, un de Dekodierungsoperation wird in'm klassischen Nachbearbeitungsschritt angelegt.
In der Beschreibung hier oben kann de Dekodierungsoperation durchjeführt wern, indem Quantengatter uff de Site-Qubits angelegt wern, um'n Quantenzustand wiederherzustellen. Aber wenn das Ziel is, den Zustand sofort zu messen, zum Beispiel für Charakterisierungszwecke, dann wern de Site-Qubits zusammen mit de Bond-Qubits gemessen, un de Dekodierungsoperation kann in'm klassischen Nachbearbeitungsschritt angelegt wern. So is das Experiment in der GEM Suite implementiert, was diesem Tutorial folgt.
Zusätzlich dazu, dass es vom Winkel in Schritt 2 abhängt, der standardmäßig über 21 Werte jeht, hängt der GEM-Protokoll-Schaltkreis ooch vom Zeitplan-Muster ab, was verwendet wird, um de 3 Schichten von Gattern zu implementieren. Wie vorher besprochen jibt's 12 solche Zeitplan-Muster. Deswegen is de jesamte Anzahl von Schaltkreisen im Experiment .
De Schaltkreise vom Experiment können mitder circuits Methode von der GemExperiment Klasse erzeugt wern.
circuits = gem_exp.circuits()
print(f"Total number of circuits: {len(circuits)}")
Total number of circuits: 252
Für de Zwecke von diesem Tutorial is es jenug, nur'n einzelnes Zeitplan-Muster zu betrachten. De nächste Code-Zelle beschränkt das Experiment uffs erste Zeitplan-Muster. Damit hat das Experiment nur 21 Schaltkreise, eener für jeden Winkel, über den jejangen wird.
# 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]
De nächste Code-Zelle zeigt'n Diagramm vom Schaltkreis bei Index 5. Um de Größe vom Diagramm zu reduzieren, wern de Messungs-Gatter am Ende vom Schaltkreis 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)
Schritt 2: Problem für Quanten-Hardware-Ausführung optimieren
Das Transpilieren von Quantenschaltkreisen für de Ausführung uff Hardware umfasst typischerweise ne ganze Reihe von Etappen. Typischerweise sin de Etappen, de am meisten rechenintensiv sin, de Auswahl vom Qubit-Layout, das Routing von de Zwei-Qubit-Gattern, um sich an de Qubit-Konnektivität von der Hardware anzupassen, un de Optimierung vom Schaltkreis, um seine Gatter-Anzahl un Tiefe zu minimieren. Im GEM-Protokoll sin de Layout- un Routing-Etappen unnötig, weil de Hardware-Konnektivität schon ins Design vom Protokoll eingebaut is. De Schaltkreise ham schon'n Qubit-Layout, un de Zwei-Qubit-Gatter sin schon uff native Verbindungen abgebildet. Darüber hinaus sollte nur sehr einfache Schaltkreis-Optimierung durchjeführt wern, um de Struktur vom Schaltkreis zu erhalten, wenn der Winkel variiert wird.
De GemExperiment Klasse transpiliert Schaltkreise transparent, wenn das Experiment durchjeführt wird. De Layout- un Routing-Etappen sin standardmäßig schon überschrieben, um nix zu tun, un Schaltkreis-Optimierung wird uffm Niveau durchjeführt, was nur Ein-Qubit-Gatter optimiert. Aber de kannst zusätzliche Optionen überschreiben oder anjeben, indem de de set_transpile_options Methode verwendest. Für de Zwecke von der Visualisierung transpiliert de nächste Code-Zelle manuell den Schaltkreis, der vorher anjezeigt wurde, un zeigt 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=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)

Schritt 3: Mit Qiskit Primitives ausführen
Um de GEM-Protokoll-Schaltkreise uff der Hardware auszuführen, ruf de run Methode vom GemExperiment Objekt uff. De kannst de Anzahl von Shots anjeben, de de aus jedem Schaltkreis sampeln willst. De run Methode liefert'n ExperimentData Objekt, was de inner Variable speichern solltest. Beachte, dass de run Methode nur Jobs einreicht ohne uff se zu warten bis se fertig sin, so dass's'n nich-blockierender Aufruf is.
exp_data = gem_exp.run(shots=10_000)
Um uff de Erjebnisse zu warten, ruf de block_for_results Methode vom ExperimentData Objekt uff. Dieser Aufruf lässt den Interpreter hängen, bis de Jobs fertig sin.
exp_data.block_for_results()
ExperimentData(GemExperiment, d0d5880a-34c1-4aab-a7b6-c4f58516bc03, job_ids=['cwg12ptmptp00082khhg'], metadata=<5 items>, figure_names=['two_point_correlation.svg', 'normalized_variance.svg', 'plaquette_ops.svg', 'bond_ops.svg'])
Schritt 4: Nachbearbeiten un Erjebniss im jewünschten klassischen Format zurückjeben
Beim Winkel von würde der dekodierte Zustand der GHZ-Zustand in Abwesenheit von Rauschen sein. De Langstreckenordnung vom GHZ-Zustand kann visualisiert wern, indem de Magnetisierung von de jemessenen Bitstrings abgebildet wird. De Magnetisierung wird definiert als de Summe von de Ein-Qubit-Pauli Operatoren,
wo de Anzahl von Site-Qubits is. Sein Wert für'n Bitstring is gleich dem Unterschied zwischn der Anzahl von Nullen un der Anzahl von Einsen. Das Messen vom GHZ-Zustand liefert den all-Null Zustand oder den all-Eins Zustand mit jleicher Wahrscheinlichkeit, so dass de Magnetisierung de halbe Zeit un de annere halbe Zeit wäre. In der Anwesenheit von Fehlern wejen Rauschen würden ooch annere Werte ufftreten, aber wenn das Rauschen nich zu groß is, würde de Verteilung noch immer Spitzen bei un zeigen.
Für de rohen Bitstrings vor der Dekodierung würde de Verteilung von der Magnetisierung gleichbedeutend mit denen von jleichmäßig zufälligen Bitstrings sein, in Abwesenheit von Rauschen.
De nächste Code-Zelle zeigt de Magnetisierung von de rohen Bitstrings un de dekodierten Bitstrings beim Winkel von .
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')
Um de Langstreckenordnung rigoroser zu charakterisieren, kannst de de durchschnittliche Zwei-Punkt-Korrelation betrachten, definiert als
'n höherer Wert zeigt'n größern Jrad von Verschränkung an. De GemExperiment Klasse berechnet diesen Wert automatisch für de dekodierten Bitstrings als Teil von der Verarbeitung von de experimentellen Daten. De speichert'n Diagramm, was über de figure Methode von der Experiment-Daten-Klasse zugreifbar is. In diesem Fall heißt das Diagramm two_point_correlation.
exp_data.figure("two_point_correlation")
Um den kritischen Punkt vom Nishimori Phasenübergang zu bestimmen, kannst de uff de normalisierte Varianz von gucken, definiert als
was de Stärke von der Schwankung in der quadrierten Magnetisierung quantifiziert. Dieser Wert is maximal am kritischen Punkt vom Nishimori Phasenübergang. In Abwesenheit von Rauschen tritt der kritische Punkt bei ungefähr uff. In Anwesenheit von Rauschen wird der kritische Punkt nach oben verschoben, aber der Phasenübergang wird noch immer beobachtet, solange der kritische Punkt unter liegt.
exp_data.figure("normalized_variance")
Das Experiment aufskalieren
De nächsten Code-Zellen führen das Experiment für sechs Plaketten (49 Qubits) un de vollen 12 Plaketten (125 Qubits) durch un zeigen de normalisierte Varianz. Wenn das Experiment uff größere Größen aufskaliert wird, verschiebt de größere Menge von Rauschen den kritischen Punkt nach rechts.
gem_exp = GemExperiment(
plaquette_lattice.filter(range(3, 9)), backend=backend
)
gem_exp.set_experiment_options(schedule_idx=0)
exp_data = gem_exp.run(shots=10_000)
exp_data.block_for_results()
exp_data.figure("normalized_variance")
gem_exp = GemExperiment(plaquette_lattice, backend=backend)
gem_exp.set_experiment_options(schedule_idx=0)
exp_data = gem_exp.run(shots=10_000)
exp_data.block_for_results()
exp_data.figure("normalized_variance")
Fazit
In diesem Tutorial hast de'n Nishimori Phasenübergang uffm Quantenprozessor mitm GEM-Protokoll realisiert. De Metriken, de de während der Nachbearbeitung untersucht hast, besonders de Zwei-Punkt-Korrelation un de normalisierte Varianz, dienen als Benchmarks für de Fähigkeit vom Gerät, langstrecken verschränkte Zustände zu jenerieren. Diese Benchmarks erweitern den Nutzen vom GEM-Protokoll über das Erforschen von interessanter Physik hinaus. Als Teil vom Protokoll hast de Qubits übern ganzen Gerät verschränkt mit Schaltkreisen von nur konstanter Tiefe. Diese Kunststück is nur möglich durchs Verwenden von Messungen innerhalb vom Schaltkreis vom Protokoll. In diesem Experiment wurde der verschränkte Zustand sofort jemessen, aber'n interessanter Wej, den mr erforschen könnte, wäre, den Zustand weiter zu verwenden in zusätzlicher Quantenverarbeitung!
Tutorial-Umfrage
Bitte nimm an dieser kurzen Umfrage teil, um Feedback zu diesem Tutorial zu jeben. Deine Einsichten helfen uns, unser Inhalts-Anjebot un Benutzererfahrung zu verbessern.