Przejdź do głównej treści

Przejście fazowe Nishimoriego

Szacowany czas użycia: 3 minuty na procesorze Heron r2 (UWAGA: To jest jedynie szacunek. Rzeczywisty czas może się różnić.)

Efekty kształcenia

Po ukończeniu tego samouczka użytkownicy powinni osiągnąć następujące efekty:

  • Rozumieć przejście fazowe Nishimoriego oraz to, jak objawia się ono jako pojawienie się dalekosiężnego splątania w modelu Isinga z losowymi wiązaniami.
  • Implementować protokół generowania splątania przez pomiar (GEM) na sprzęcie kwantowym z wykorzystaniem pomiarów w trakcie obwodu i obwodów o stałej głębokości.
  • Charakteryzować przejście fazowe poprzez wyznaczanie dwupunktowej korelacji i znormalizowanej wariancji magnetyzacji z danych eksperymentalnych.

Wymagania wstępne

Zalecamy zaznajomienie się z następującymi zagadnieniami przed rozpoczęciem tego samouczka:

Tło

Ten samouczek pokazuje, jak zrealizować przejście fazowe Nishimoriego na procesorze kwantowym. Eksperyment został pierwotnie opisany w artykule Realizing the Nishimori transition across the error threshold for constant-depth quantum circuits.

Przejście fazowe Nishimoriego oznacza przejście między fazami o krótko- i dalekosiężnym porządku w modelu Isinga z losowymi wiązaniami. Na komputerze kwantowym faza o dalekosiężnym porządku objawia się stanem, w którym qubity są ze sobą splątane w całym urządzeniu. Ten silnie splątany stan jest przygotowywany przy użyciu protokołu generowania splątania przez pomiar (GEM). Dzięki wykorzystaniu pomiarów w trakcie obwodu protokół GEM jest w stanie splątać qubity w całym urządzeniu za pomocą obwodów o stałej głębokości. W tym samouczku stosowana jest implementacja protokołu GEM z pakietu oprogramowania GEM Suite.

Wymagania

Przed rozpoczęciem tego samouczka upewnij się, że masz zainstalowane następujące elementy:

  • Qiskit SDK v1.0 lub nowszy z obsługą wizualizacji
  • Qiskit Runtime v0.22 lub nowszy (pip install qiskit-ibm-runtime)
  • Qiskit Aer v0.14 lub nowszy (pip install qiskit-aer)
  • GEM Suite (pip install gem-suite)

Konfiguracja

# 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

Przykład symulacji na małą skalę

W tej sekcji przeprowadzimy pełny przepływ pracy na bezszumowym AerSimulator. Sieć plakietek jest ograniczona do jednej plakietki (12 qubitów), dzięki czemu symulacja pozostaje mała i szybka, jednocześnie ćwicząc każdą część protokołu GEM: pomiar w trakcie obwodu, przemiatanie kąta RZZR_{ZZ}, dekodowanie i analizę znormalizowanej wariancji. Ten sam przepływ pracy jest później skalowany do wielu plakietek i pełnej sieci na rzeczywistym sprzęcie.

Krok 1: Odwzorowanie danych wejściowych na problem kwantowy

Protokół GEM działa na procesorze kwantowym, którego topologia połączeń qubitów jest opisana przez sieć krystaliczną. Współczesne procesory kwantowe IBM Quantum® używają sieci heavy-hex. Qubity procesora są grupowane w plakietki na podstawie komórki jednostkowej sieci, w której się znajdują. Ponieważ qubit może wystąpić w więcej niż jednej komórce jednostkowej, plakietki nie są rozłączne. W sieci heavy-hex plakietka zawiera 12 qubitów. Same plakietki również tworzą sieć, gdzie dwie plakietki są połączone, jeśli mają wspólne qubity. W sieci heavy-hex sąsiednie plakietki mają 3 wspólne qubity.

W pakiecie oprogramowania GEM Suite podstawową klasą do implementacji protokołu GEM jest PlaquetteLattice, która reprezentuje sieć plakietek (odrębną od sieci heavy-hex). Obiekt PlaquetteLattice można zainicjować na podstawie mapy sprzężeń qubitów. Obecnie obsługiwane są tylko mapy sprzężeń heavy-hex.

Poniższa komórka kodu inicjuje sieć plakietek na podstawie mapy sprzężeń jednostki przetwarzania kwantowego (QPU). Sieć plakietek nie zawsze obejmuje całe urządzenie. Na przykład ibm_torino ma łącznie 133 qubity, ale największa sieć plakietek, która mieści się na urządzeniu, używa tylko 125 z nich, tworząc 18 plakietek; ibm_pittsburgh (156 qubitów) analogicznie mieści 144 qubity w 21 plakietkach. Ten sam wzorzec dotyczy innych QPU heavy-hex z różną liczbą qubitów.

# 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()))}")

Możesz zwizualizować sieć plakietek, generując diagram jej reprezentacji grafowej. Na diagramie plakietki są przedstawiane jako oznakowane sześciokąty, a dwie plakietki są połączone krawędzią, jeśli mają wspólne qubity.

plaquette_lattice.draw_plaquettes()

Output of the previous code cell

Możesz uzyskać informacje o poszczególnych plakietkach, takie jak zawarte w nich qubity, używając metody plaquettes.

# 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])

Możesz również wygenerować diagram bazowych qubitów tworzących sieć plakietek.

plaquette_lattice.draw_qubits()

Output of the previous code cell

Oprócz etykiet qubitów i krawędzi wskazujących połączone qubity diagram zawiera trzy dodatkowe informacje istotne dla protokołu GEM:

  • Każdy qubit jest albo zacieniony (szary), albo niezacieniony. Zacienione qubity to qubity „węzłowe" reprezentujące węzły modelu Isinga, a niezacienione qubity to qubity „wiązaniowe" służące do pośredniczenia w interakcjach między qubitami węzłowymi.
  • Każdy qubit węzłowy jest oznaczony (A) lub (B), wskazując jedną z dwóch ról, jaką qubit węzłowy może odgrywać w protokole GEM (role są wyjaśnione później).
  • Każda krawędź jest zabarwiona jednym z sześciu kolorów, dzieląc krawędzie na sześć grup. Ten podział określa, jak bramki dwuqubitowe mogą być zrównoleglone, a także różne wzorce harmonogramowania, które prawdopodobnie wprowadzają różne ilości błędów na zaszumionym procesorze kwantowym. Ponieważ krawędzie w grupie są rozłączne, warstwa bramek dwuqubitowych może być zastosowana do tych krawędzi jednocześnie. W rzeczywistości możliwe jest podzielenie sześciu kolorów na trzy grupy po dwa kolory tak, że suma każdej grupy dwóch kolorów jest nadal rozłączna. Dlatego do aktywacji każdej krawędzi potrzebne są tylko trzy warstwy bramek dwuqubitowych. Istnieje 12 sposobów takiego podziału sześciu kolorów, a każdy taki podział daje inny trójwarstwowy harmonogram bramek.

Teraz, gdy masz już sieć plakietek, następnym krokiem jest zainicjowanie obiektu GemExperiment, przekazując zarówno sieć plakietek, jak i backend, na którym zamierzasz przeprowadzić eksperyment. Klasa GemExperiment zarządza rzeczywistą implementacją protokołu GEM, w tym generowaniem obwodów, przesyłaniem zadań i analizą danych. Poniższa komórka kodu inicjuje klasę eksperymentu, ograniczając sieć plakietek tylko do jednej plakietki (12 qubitów), co utrzymuje symulację małą i szybką. Pełna sieć plakietek jest używana później podczas skalowania do rzeczywistego sprzętu.

# 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

Obwód protokołu GEM jest budowany przy użyciu następujących kroków:

  1. Przygotuj stan +|+\rangle dla wszystkich qubitów, stosując bramkę Hadamarda do każdego qubitu.
  2. Zastosuj bramkę RZZR_{ZZ} między każdą parą połączonych qubitów. Można to osiągnąć przy użyciu trzech warstw bramek. Każda bramka RZZR_{ZZ} działa na qubit węzłowy i qubit wiązaniowy. Jeśli qubit węzłowy jest oznaczony (B), kąt jest ustalony na π2\frac{\pi}{2}. Jeśli qubit węzłowy jest oznaczony (A), kąt może się zmieniać, tworząc różne obwody. Domyślnie zakres kątów jest ustawiony na 21 równomiernie rozmieszczonych punktów między 00 a π2\frac{\pi}{2}, włącznie.
  3. Zmierz każdy qubit wiązaniowy w bazie Pauliego XX. Ponieważ qubity są mierzone w bazie Pauliego ZZ, można to osiągnąć, stosując bramkę Hadamarda przed pomiarem qubitu.

Zauważ, że artykuł cytowany we wstępie do tego samouczka używa innej konwencji dla kąta RZZR_{ZZ}, która różni się od konwencji stosowanej w tym samouczku czynnikiem 2.

W kroku trzecim mierzone są tylko qubity wiązaniowe. Aby zrozumieć, w jakim stanie pozostają qubity węzłowe, pouczające jest rozważenie przypadku, gdy kąt RZZR_{ZZ} zastosowany do qubitów węzłowych (A) w kroku 2 wynosi π2\frac{\pi}{2}. W tym przypadku qubity węzłowe pozostają w silnie splątanym stanie podobnym do stanu GHZ,

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

Ze względu na losowość wyników pomiarów rzeczywisty stan qubitów węzłowych może być innym stanem o dalekosiężnym porządku, na przykład 00110+11001\lvert 00110 \rangle + \lvert 11001 \rangle. Jednak stan GHZ można odzyskać, stosując operację dekodowania opartą na wynikach pomiarów. Gdy kąt RZZR_{ZZ} jest zmniejszany z π2\frac{\pi}{2}, dalekosiężny porządek można nadal odzyskać aż do kąta krytycznego, który w przypadku braku szumu wynosi około 0.3π0.3 \pi. Poniżej tego kąta wynikowy stan nie wykazuje już dalekosiężnego splątania. To przejście między obecnością a brakiem dalekosiężnego porządku jest właśnie przejściem fazowym Nishimoriego.

W powyższym opisie qubity węzłowe pozostały niezmierzone, a operacja dekodowania może być wykonana przez zastosowanie bramek kwantowych. W eksperymencie zaimplementowanym w pakiecie GEM Suite qubity węzłowe są w rzeczywistości mierzone, a operacja dekodowania jest stosowana w kroku klasycznego post-processingu.

W powyższym opisie operacja dekodowania może być wykonana przez zastosowanie bramek kwantowych do qubitów węzłowych w celu odzyskania stanu kwantowego. Jednak jeśli celem jest natychmiastowe zmierzenie stanu (na przykład w celach charakteryzacji), qubity węzłowe można zmierzyć razem z qubitami wiązaniowymi i zastosować operację dekodowania w klasycznym kroku post-processingu.

Oprócz zależności od kąta RZZR_{ZZ} w kroku 2, który domyślnie przyjmuje 21 wartości, obwód protokołu GEM zależy również od wzorca harmonogramowania używanego do implementacji trzech warstw bramek RZZR_{ZZ}. Jak omówiono wcześniej, istnieje 12 takich wzorców harmonogramowania. Dlatego łączna liczba obwodów w eksperymencie wynosi 21×12=25221 \times 12 = 252.

Obwody eksperymentu można wygenerować przy użyciu metody circuits klasy GemExperiment.

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

Na potrzeby tego samouczka wystarczy rozważyć tylko jeden wzorzec harmonogramowania. Poniższa komórka kodu ogranicza eksperyment do pierwszego wzorca harmonogramowania. W rezultacie eksperyment ma tylko 21 obwodów, po jednym dla każdego przemiatanego kąta RZZR_{ZZ}.

# 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]

Poniższa komórka kodu rysuje diagram obwodu o indeksie 5. Aby zmniejszyć rozmiar diagramu, bramki pomiarowe na końcu obwodu są usunięte.

# 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

Krok 2: Optymalizacja problemu pod kątem wykonania na sprzęcie kwantowym

Transpilacja obwodów kwantowych do wykonania na sprzęcie zazwyczaj obejmuje kilka etapów. Etapy powodujące największe obciążenie obliczeniowe to zazwyczaj wybór układu qubitów, trasowanie bramek dwuqubitowych zgodnie z topologią połączeń sprzętu oraz optymalizacja obwodu w celu minimalizacji liczby bramek i głębokości. W protokole GEM etapy układu i trasowania są zbędne, ponieważ topologia sprzętu jest już wbudowana w projekt protokołu. Obwody mają już układ qubitów, a bramki dwuqubitowe są już odwzorowane na natywne połączenia. Ponadto, aby zachować strukturę obwodu przy zmiennym kącie RZZR_{ZZ}, powinna być wykonywana tylko bardzo podstawowa optymalizacja obwodu.

Klasa GemExperiment transparentnie transpiluje obwody podczas wykonywania eksperymentu. Etapy układu i trasowania są już domyślnie zastąpione przez operacje nierobienia niczego, a optymalizacja obwodu jest wykonywana na poziomie, który optymalizuje jedynie bramki jednoqubitowe. Możesz jednak nadpisać lub przekazać dodatkowe opcje przy użyciu metody set_transpile_options. Dla celów wizualizacji poniższa komórka kodu ręcznie transpiluje wcześniej wyświetlony obwód i rysuje transpilowany obwód.

# 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

Krok 3: Wykonanie przy użyciu prymitywów Qiskit

Aby wykonać obwody protokołu GEM na sprzęcie, wywołaj metodę run obiektu GemExperiment. Możesz określić liczbę próbek (shots) do pobrania z każdego obwodu. Metoda run zwraca obiekt ExperimentData, który powinieneś zapisać do zmiennej. Zauważ, że metoda run jedynie przesyła zadania bez oczekiwania na ich zakończenie, więc jest to wywołanie nieblokujące.

exp_data = gem_exp.run(shots=10_000)

Aby poczekać na wyniki, wywołaj metodę block_for_results obiektu ExperimentData. To wywołanie spowoduje zatrzymanie interpretera do momentu zakończenia zadań.

# 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'])

Krok 4: Post-processing i zwracanie wyników w żądanym formacie klasycznym

Przy kącie RZZR_{ZZ} wynoszącym π2\frac{\pi}{2} zdekodowany stan byłby stanem GHZ w przypadku braku szumu. Dalekosiężny porządek stanu GHZ można zwizualizować, kreśląc magnetyzację zmierzonych ciągów bitów. Magnetyzacja MM jest zdefiniowana jako suma jednoqubitowych operatorów Pauliego ZZ,

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

gdzie NN jest liczbą qubitów węzłowych. Jej wartość dla ciągu bitów jest równa różnicy między liczbą zer a liczbą jedynek. Pomiar stanu GHZ daje stan wszystkich zer lub stan wszystkich jedynek z równym prawdopodobieństwem, więc magnetyzacja wynosiłaby +N+N przez połowę czasu i N-N przez drugą połowę. W obecności błędów spowodowanych szumem pojawiałyby się również inne wartości, ale jeśli szum nie jest zbyt duży, rozkład nadal byłby skupiony blisko +N+N i N-N.

Dla surowych ciągów bitów przed dekodowaniem rozkład magnetyzacji byłby równoważny rozkładowi dla losowych ciągów bitów, w przypadku braku szumu.

Poniższa komórka kodu kreśli magnetyzację surowych ciągów bitów i zdekodowanych ciągów bitów przy kącie RZZR_{ZZ} wynoszącym π2\frac{\pi}{2}.

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

Aby dokładniej scharakteryzować dalekosiężny porządek, możesz zbadać średnią dwupunktową korelację ff, zdefiniowaną jako

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

Wyższa wartość wskazuje na większy stopień splątania. Klasa GemExperiment automatycznie oblicza tę wartość dla zdekodowanych ciągów bitów w ramach przetwarzania danych eksperymentalnych. Przechowuje rysunek dostępny za pomocą metody figure klasy danych eksperymentu. W tym przypadku nazwa rysunku to two_point_correlation.

exp_data.figure("two_point_correlation")

Output of the previous code cell

Aby określić punkt krytyczny przejścia fazowego Nishimoriego, możesz spojrzeć na znormalizowaną wariancję M2/NM^2 / N, zdefiniowaną jako

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

która kwantyfikuje wielkość fluktuacji w kwadracie magnetyzacji. Wartość ta jest maksymalna w punkcie krytycznym przejścia fazowego Nishimoriego. W przypadku braku szumu punkt krytyczny występuje przy około 0.3π0.3 \pi. W obecności szumu punkt krytyczny przesuwa się wyżej, ale przejście fazowe jest nadal obserwowane, o ile punkt krytyczny występuje poniżej 0.5π0.5 \pi.

exp_data.figure("normalized_variance")

Output of the previous code cell

Przykład sprzętowy na dużą skalę

Po zwalidowaniu protokołu na symulatorze możesz teraz skalować eksperyment i uruchomić go na rzeczywistym backendzie sprzętu kwantowego wybranym w sekcji Konfiguracja. Ten przykład używa dwóch większych rozmiarów problemu:

  • Sześć plakietek (~49 qubitów): uruchomienie w średniej skali, które już pokazuje przesunięcie punktu krytycznego w prawo pod wpływem szumu sprzętowego.
  • Pełna sieć plakietek: wszystkie plakietki obsługiwane przez topologię heavy-hex urządzenia (na przykład 18 plakietek / 125 qubitów na ibm_torino lub 21 plakietek / 144 qubity na ibm_pittsburgh), splątując qubity w całym urządzeniu za pomocą obwodów o stałej głębokości.

Pojedyncza komórka kodu poniżej jest samowystarczalna: buduje sieć plakietek na podstawie mapy sprzężeń backendu i uruchamia oba eksperymenty, więc tę sekcję można wykonać po komórkach Konfiguracja bez wcześniejszego uruchamiania sekcji na małą skalę.

# -------------------------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

Należy pamiętać, że w zależności od poziomu szumu użytego backendu krzywe znormalizowanej wariancji dla większych rozmiarów mogą nie wykazywać wyraźnego szczytu w przemiatamy zakresie kątów. W powyższych uruchomieniach szczyt został przesunięty aż do 0.5π0.5 \pi, prawej krawędzi przemiatania (analiza podaje critical_angle = 0.5000 zarówno dla uruchomień sześcioplakietkowych, jak i pełnosieciowych). Oznacza to, że szum sprzętowy przesunął punkt krytyczny do (lub tuż za) granicy fizycznie sensownego zakresu kątów protokołu, więc przejście fazowe jest na krawędzi tego, co to przemiatanie może rozwiązać.

Podsumowanie

W tym samouczku zrealizowałeś przejście fazowe Nishimoriego na procesorze kwantowym przy użyciu protokołu GEM. Metryki zbadane podczas post-processingu — w szczególności korelacja dwupunktowa i znormalizowana wariancja — służą jako wskaźniki zdolności urządzenia do generowania stanów o dalekosiężnym splątaniu. Te wskaźniki rozszerzają użyteczność protokołu GEM poza sondowanie interesującej fizyki. W ramach protokołu splątałeś qubity w całym urządzeniu przy użyciu obwodów o stałej głębokości. Ten wyczyn jest możliwy tylko dzięki zastosowaniu w protokole pomiarów w trakcie obwodu. W tym eksperymencie splątany stan został natychmiast zmierzony, ale rozważ dalszą eksplorację, wykorzystując ten stan w dodatkowych obliczeniach kwantowych.

Następne kroki

Zalecenia

Jeśli to zagadnienie wydało ci się interesujące, być może zainteresują cię następujące materiały:

Odniesienia

[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 software package.