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ć.)
Wprowadzenie
Ten samouczek pokazuje, jak zrealizować przejście fazowe Nishimoriego na procesorze kwantowym IBM®. 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) - GEM Suite (
pip install gem-suite)
Konfiguracja
# Added by doQumentation — required packages for this notebook
!pip install -q gem-suite matplotlib qiskit qiskit-ibm-runtime
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
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 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ń procesora kwantowego IBM. 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 i składa się z 18 plakietek. Podobne sytuacje można zaobserwować na urządzeniach IBM Quantum® z różną liczbą qubitów.
# 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
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()
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=[0, 1, 2, 3, 4, 15, 16, 19, 20, 21, 22, 23], neighbors=[3, 1])
Możesz również wygenerować diagram bazowych qubitów tworzących sieć plakietek.
plaquette_lattice.draw_qubits()

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 harmonogram 3-warstwowy.
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 dwóch plakietek (21 qubitów), co zmniejsza rozmiar eksperymentu, aby upewnić się, że szum sprzętu nie zdominuje sygnału.
gem_exp = GemExperiment(plaquette_lattice.filter([9, 12]), backend=backend)
# visualize the plaquette lattice after filtering
plaquette_lattice.filter([9, 12]).draw_qubits()

Obwód protokołu GEM jest budowany przy użyciu następujących kroków:
- Przygotuj stan dla wszystkich qubitów, stosując bramkę Hadamarda do każdego qubitu.
- Zastosuj bramkę między każdą parą połączonych qubitów. Można to osiągnąć przy użyciu 3 warstw bramek. Każda bramka 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 . 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 a , włącznie.
- Zmierz każdy qubit wiązaniowy w bazie Pauliego . Ponieważ qubity są mierzone w bazie Pauliego , 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 , która różni się od konwencji stosowanej w tym samouczku czynnikiem 2.
W kroku 3 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 zastosowany do qubitów węzłowych (A) w kroku 2 wynosi . W tym przypadku qubity węzłowe pozostają w silnie splątanym stanie podobnym do stanu GHZ,
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 . Jednak stan GHZ można odzyskać, stosując operację dekodowania opartą na wynikach pomiarów. Gdy kąt jest zmniejszany z , dalekosiężny porządek można nadal odzyskać aż do kąta krytycznego, który w przypadku braku szumu wynosi około . 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, za którym podąża ten samouczek, 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 są mierzone razem z qubitami wiązaniowymi, a operacja dekodowania może być zastosowana w klasycznym kroku post-processingu. W ten sposób eksperyment jest zaimplementowany w pakiecie GEM, za którym podąża ten samouczek.
Oprócz zależności od kąta 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 3 warstw bramek . Jak omówiono wcześniej, istnieje 12 takich wzorców harmonogramowania. Dlatego łączna liczba obwodów w eksperymencie wynosi .
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 .
# 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)
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 , 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=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)

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ń.
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'])
Krok 4: Post-processing i zwracanie wyników w żądanym formacie klasycznym
Przy kącie wynoszącym 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 jest zdefiniowana jako suma jednoqubitowych operatorów Pauliego ,
gdzie 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 przez połowę czasu i 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 i .
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 wynoszącym .
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')
Aby dokładniej scharakteryzować dalekosiężny porządek, możesz zbadać średnią korelację dwupunktową , zdefiniowaną jako
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")
Aby określić punkt krytyczny przejścia fazowego Nishimoriego, możesz spojrzeć na znormalizowaną wariancję , zdefiniowaną jako
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 . 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 .
exp_data.figure("normalized_variance")
Skalowanie eksperymentu
Poniższe komórki kodu przeprowadzają eksperyment dla sześciu plakietek (49 qubitów) i pełnych 12 plakietek (125 qubitów) oraz kreślą znormalizowaną wariancję. W miarę skalowania eksperymentu do większych rozmiarów większa ilość szumu przesuwa punkt krytyczny w prawo.
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")
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 interesującym kierunkiem do eksploracji byłoby dalsze wykorzystanie tego stanu w dodatkowych obliczeniach kwantowych!
Ankieta dotycząca samouczka
Wypełnij tę krótką ankietę, aby przekazać opinię na temat tego samouczka. Twoje uwagi pomogą nam ulepszyć naszą ofertę treści i doświadczenie użytkownika.
Note: This survey is provided by IBM Quantum and relates to the original English content. To give feedback on doQumentation's website, translations, or code execution, please open a GitHub issue.