Nierówność CHSH
Szacowany czas użycia: dwie minuty na procesorze Heron r2 (UWAGA: Jest to jedynie szacunek. Rzeczywisty czas wykonania może się różnić.)
Tło
W tym samouczku przeprowadzisz eksperyment na komputerze kwantowym, aby zademonstrować naruszenie nierówności CHSH za pomocą prymitywu Estimator.
Nierówność CHSH, nazwana od nazwisk autorów Clauser, Horne, Shimony i Holt, służy do eksperymentalnego udowodnienia twierdzenia Bella (1969). Twierdzenie to głosi, że lokalne teorie ze zmiennymi ukrytymi nie mogą wyjaśnić niektórych konsekwencji splątania w mechanice kwantowej. Naruszenie nierówności CHSH jest używane do wykazania, że mechanika kwantowa jest niezgodna z lokalnymi teoriami ze zmiennymi ukrytymi. Jest to ważny eksperyment dla zrozumienia podstaw mechaniki kwantowej.
Nagroda Nobla z fizyki w 2022 roku została przyznana Alainowi Aspectowi, Johnowi Clauserowi i Antonowi Zeilingerowi między innymi za ich pionierską pracę w dziedzinie kwantowej nauki o informacji, a w szczególności za eksperymenty ze splątanymi fotonami demonstrujące naruszenie nierówności Bella.
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 (
pip install qiskit-ibm-runtime) v0.22 lub nowszy
Konfiguracja
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-ibm-runtime
# General
import numpy as np
# Qiskit imports
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
# Qiskit Runtime imports
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import EstimatorV2 as Estimator
# Plotting routines
import matplotlib.pyplot as plt
import matplotlib.ticker as tck
Krok 1: Odwzoruj klasyczne dane wejściowe na problem kwantowy
W tym eksperymencie stworzymy splątaną parę, w której mierzymy każdy qubit w dwóch różnych bazach. Oznaczmy bazy dla pierwszego qubitu jako i , a bazy dla drugiego qubitu jako i . Pozwala nam to obliczyć wielkość CHSH :
Każda obserwabla przyjmuje wartość lub . Oczywiście jeden z wyrazów musi być równy , a drugi . Zatem . Wartość średnia musi spełniać nierówność:
Rozwijając w kategoriach , , i , otrzymujemy:
Możesz zdefiniować kolejną wielkość CHSH :
Co prowadzi do kolejnej nierówności:
Jeśli mechanika kwantowa może być opisana przez lokalne teorie ze zmiennymi ukrytymi, poprzednie nierówności muszą być spełnione. Jednak, jak zostaje zademonstrowane w tym samouczku, nierówności te mogą być naruszone przez komputer kwantowy. Zatem mechanika kwantowa nie jest zgodna z lokalnymi teoriami ze zmiennymi ukrytymi. Jeśli chcesz poznać więcej teorii, zapoznaj się z Splątaniem w działaniu z Johnem Watrousem. Stworzysz splątaną parę między dwoma qubitami w komputerze kwantowym, tworząc stan Bella . Używając prymitywu Estimator, możesz bezpośrednio uzyskać potrzebne wartości oczekiwane ( i ), aby obliczyć wartości oczekiwane obu wielkości CHSH i . Przed wprowadzeniem prymitywu Estimator musiałbyś konstruować wartości oczekiwane na podstawie wyników pomiarów.
Będziesz mierzyć drugi qubit w bazach i . Pierwszy qubit będzie mierzony również w prostopadłych bazach, ale pod kątem względem drugiego qubitu, który będziemy przesuwać między a . Jak zobaczysz, prymityw Estimator sprawia, że uruchamianie sparametryzowanych obwodów jest bardzo proste. Zamiast tworzyć serię obwodów CHSH, wystarczy stworzyć jeden obwód CHSH z parametrem określającym kąt pomiaru oraz serię wartości fazy dla tego parametru.
Na koniec przeanalizujesz wyniki i wykreślisz je w funkcji kąta pomiaru. Zobaczysz, że dla pewnego zakresu kątów pomiaru wartości oczekiwane wielkości CHSH spełniają lub , co demonstruje naruszenie nierówności CHSH.
# To run on hardware, select the backend with the fewest number of jobs in the queue
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
)
backend.name
'ibm_kingston'
Utwórz sparametryzowany obwód CHSH
Najpierw zapiszemy obwód z parametrem , który nazywamy theta. Prymityw Estimator może znacznie uprościć budowanie obwodów i analizę wyników, bezpośrednio podając wartości oczekiwane obserwabli. Wiele problemów będących przedmiotem zainteresowania, zwłaszcza w zastosowaniach krótkoterminowych na zaszumionych systemach, można sformułować w kategoriach wartości oczekiwanych. Prymityw Estimator (V2) może automatycznie zmieniać bazę pomiarową na podstawie dostarczonej obserwabli.
theta = Parameter("$\\theta$")
chsh_circuit = QuantumCircuit(2)
chsh_circuit.h(0)
chsh_circuit.cx(0, 1)
chsh_circuit.ry(theta, 0)
chsh_circuit.draw(output="mpl", idle_wires=False, style="iqp")
Utwórz listę wartości fazy do późniejszego przypisania
Po utworzeniu sparametryzowanego obwodu CHSH stworzysz listę wartości fazy, które zostaną przypisane do obwodu w następnym kroku. Możesz użyć poniższego kodu, aby utworzyć listę 21 wartości fazy w zakresie od do z równymi odstępami, czyli , , , ..., , .
number_of_phases = 21
phases = np.linspace(0, 2 * np.pi, number_of_phases)
# Phases need to be expressed as list of lists in order to work
individual_phases = [[ph] for ph in phases]
Obserwable
Teraz potrzebujemy obserwabli, z których obliczymy wartości oczekiwane. W naszym przypadku przyglądamy się prostopadłym bazom dla każdego qubitu, pozwalając sparametryzowanemu obrotowi dla pierwszego qubitu niemal ciągło przesuwać bazę pomiarową względem bazy drugiego qubitu. Wybierzemy zatem obserwable , , i .
# <CHSH1> = <AB> - <Ab> + <aB> + <ab> -> <ZZ> - <ZX> + <XZ> + <XX>
observable1 = SparsePauliOp.from_list(
[("ZZ", 1), ("ZX", -1), ("XZ", 1), ("XX", 1)]
)
# <CHSH2> = <AB> + <Ab> - <aB> + <ab> -> <ZZ> + <ZX> - <XZ> + <XX>
observable2 = SparsePauliOp.from_list(
[("ZZ", 1), ("ZX", 1), ("XZ", -1), ("XX", 1)]
)
Krok 2: Zoptymalizuj problem pod kątem wykonania na sprzęcie kwantowym
Aby skrócić łączny czas wykonania zadań, prymitywy V2 przyjmują wyłącznie obwody i obserwable zgodne z instrukcjami i połączeniami obsługiwanymi przez docelowy system (określane jako obwody i obserwable zgodne z architekturą zestawu instrukcji, ISA).
Obwód ISA
target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
chsh_isa_circuit = pm.run(chsh_circuit)
chsh_isa_circuit.draw(output="mpl", idle_wires=False, style="iqp")
Obserwable ISA
Podobnie musimy przekształcić obserwable, aby były zgodne z Backend przed uruchomieniem zadań za pomocą Runtime Estimator V2. Transformację możemy wykonać przy użyciu metody apply_layout obiektu SparsePauliOp.
isa_observable1 = observable1.apply_layout(layout=chsh_isa_circuit.layout)
isa_observable2 = observable2.apply_layout(layout=chsh_isa_circuit.layout)
Krok 3: Wykonaj przy użyciu prymitywów Qiskit
Aby wykonać cały eksperyment w jednym wywołaniu Estimator.
Możemy stworzyć prymityw Qiskit Runtime Estimator do obliczenia naszych wartości oczekiwanych. Metoda EstimatorV2.run() przyjmuje iterowalny zbiór zunifikowanych bloków prymitywnych (PUBs). Każdy PUB to iterowalny obiekt w formacie (circuit, observables, parameter_values: Optional, precision: Optional).
# To run on a local simulator:
# Use the StatevectorEstimator from qiskit.primitives instead.
estimator = Estimator(mode=backend)
pub = (
chsh_isa_circuit, # ISA circuit
[[isa_observable1], [isa_observable2]], # ISA Observables
individual_phases, # Parameter values
)
job_result = estimator.run(pubs=[pub]).result()
Krok 4: Post-przetwarzanie i zwrócenie wyniku w żądanym formacie klasycznym
Estimator zwraca wartości oczekiwane dla obu obserwabli: oraz .
chsh1_est = job_result[0].data.evs[0]
chsh2_est = job_result[0].data.evs[1]
fig, ax = plt.subplots(figsize=(10, 6))
# results from hardware
ax.plot(phases / np.pi, chsh1_est, "o-", label="CHSH1", zorder=3)
ax.plot(phases / np.pi, chsh2_est, "o-", label="CHSH2", zorder=3)
# classical bound +-2
ax.axhline(y=2, color="0.9", linestyle="--")
ax.axhline(y=-2, color="0.9", linestyle="--")
# quantum bound, +-2√2
ax.axhline(y=np.sqrt(2) * 2, color="0.9", linestyle="-.")
ax.axhline(y=-np.sqrt(2) * 2, color="0.9", linestyle="-.")
ax.fill_between(phases / np.pi, 2, 2 * np.sqrt(2), color="0.6", alpha=0.7)
ax.fill_between(phases / np.pi, -2, -2 * np.sqrt(2), color="0.6", alpha=0.7)
# set x tick labels to the unit of pi
ax.xaxis.set_major_formatter(tck.FormatStrFormatter("%g $\\pi$"))
ax.xaxis.set_major_locator(tck.MultipleLocator(base=0.5))
# set labels, and legend
plt.xlabel("Theta")
plt.ylabel("CHSH witness")
plt.legend()
plt.show()
Na wykresie linie i szare obszary wyznaczają granice; najbardziej zewnętrzne linie (kreskowano-kropkowane) wyznaczają granice kwantowe (), natomiast wewnętrzne linie (kreskowane) wyznaczają granice klasyczne (). Możesz zobaczyć, że istnieją obszary, w których wielkości świadka CHSH przekraczają granice klasyczne. Gratulacje! Pomyślnie zademonstrowano naruszenie nierówności CHSH w rzeczywistym systemie kwantowym!
Ankieta dotycząca samouczka
Wypełnij tę krótką ankietę, aby podzielić się opinią na temat tego samouczka. Twoje uwagi pomogą nam ulepszyć nasze 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.