Desigualdad CHSH
Estimación de uso: Dos minutos en un procesador Heron r2 (NOTA: Esta es solo una estimación. Su tiempo de ejecución puede variar.)
Antecedentes
En este tutorial, ejecutarás un experimento en una computadora cuántica para demostrar la violación de la desigualdad CHSH con la primitiva Estimator.
La desigualdad CHSH, nombrada por los autores Clauser, Horne, Shimony y Holt, se utiliza para probar experimentalmente el teorema de Bell (1969). Este teorema afirma que las teorías de variables ocultas locales no pueden dar cuenta de algunas consecuencias del entrelazamiento en la mecánica cuántica. La violación de la desigualdad CHSH se utiliza para mostrar que la mecánica cuántica es incompatible con teorías de variables ocultas locales. Este es un experimento importante para comprender los fundamentos de la mecánica cuántica.
El Premio Nobel de Física 2022 fue otorgado a Alain Aspect, John Clauser y Anton Zeilinger en parte por su trabajo pionero en ciencia de la información cuántica y, en particular, por sus experimentos con fotones entrelazados que demostraron la violación de las desigualdades de Bell.
Requisitos
Antes de comenzar este tutorial, asegúrate de tener instalado lo siguiente:
- Qiskit SDK v1.0 o posterior, con soporte de visualización
- Qiskit Runtime (
pip install qiskit-ibm-runtime) v0.22 o posterior
Configuración
# 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
Paso 1: Mapear entradas clásicas a un problema cuántico
Para este experimento, crearemos un par entrelazado en el cual mediremos cada qubit en dos bases diferentes. Etiquetaremos las bases para el primer qubit como y y las bases para el segundo qubit como y . Esto nos permite calcular la cantidad CHSH :
Cada observable es o . Claramente, uno de los términos debe ser , y el otro debe ser . Por lo tanto, . El valor promedio de debe satisfacer la desigualdad:
Expandir en términos de , , y resulta en:
Puedes definir otra cantidad CHSH :
Esto lleva a otra desigualdad:
Si la mecánica cuántica puede ser descrita por teorías de variables ocultas locales, las desigualdades anteriores deben cumplirse. Sin embargo, como se demuestra en este tutorial, estas desigualdades pueden ser violadas en una computadora cuántica. Por lo tanto, la mecánica cuántica no es compatible con teorías de variables ocultas locales. Si quiere aprender más teoría, explora Entanglement in Action con John Watrous. Creará un par entrelazado entre dos qubits en una computadora cuántica creando el estado de Bell . Usando la primitiva Estimator, puede obtener directamente los valores esperados necesarios ( y ) para calcular los valores esperados de las dos cantidades CHSH y . Antes de la introducción de la primitiva Estimator, tendría que construir los valores esperados a partir de los resultados de medición.
Medirá el segundo qubit en las bases y . El primer qubit también se medirá en bases ortogonales, pero con un ángulo respecto al segundo qubit, que variaremos entre y . Como verás, la primitiva Estimator hace que ejecutar circuitos parametrizados sea muy fácil. En lugar de crear una serie de circuitos CHSH, solo necesita crear un circuito CHSH con un parámetro que especifica el ángulo de medición y una serie de valores de fase para el parámetro.
Finalmente, analizará los resultados y los graficará contra el ángulo de medición. Verás que para cierto rango de ángulos de medición, los valores esperados de las cantidades CHSH o , lo que demuestra la violación de la desigualdad 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'
Crear un circuito CHSH parametrizado
Primero, escribimos el circuito con el parámetro , que llamamos theta. La primitiva Estimator puede simplificar enormemente la construcción de circuitos y el análisis de salida proporcionando directamente valores esperados de observables. Muchos problemas de interés, especialmente para aplicaciones a corto plazo en sistemas ruidosos, pueden formularse en términos de valores esperados. La primitiva Estimator (V2) puede cambiar automáticamente la base de medición basándose en el observable proporcionado.
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")
Crear una lista de valores de fase para asignar más adelante
Después de crear el circuito CHSH parametrizado, creará una lista de valores de fase para asignar al circuito en el siguiente paso. Puede usar el siguiente código para crear una lista de 21 valores de fase que van de a con espaciado igual, es decir, , , , ..., , .
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]
Observables
Ahora necesitamos observables de los cuales calcular los valores esperados. En nuestro caso estamos mirando bases ortogonales para cada qubit, permitiendo que la rotación parametrizada para el primer qubit varíe la base de medición casi continuamente con respecto a la base del segundo qubit. Por lo tanto, elegiremos los observables , , y .
# <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)]
)
Paso 2: Optimizar el problema para la ejecución en hardware cuántico
Para reducir el tiempo total de ejecución del trabajo, las primitivas V2 solo aceptan circuitos y observables que se ajustan a las instrucciones y conectividad compatibles con el sistema objetivo (denominados circuitos y observables de arquitectura de conjunto de instrucciones (ISA)).
Circuito 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")
Observables ISA
De manera similar, necesitamos transformar los observables para hacerlos compatibles con el backend antes de ejecutar trabajos con Runtime Estimator V2. Podemos realizar la transformación usando el método apply_layout del objeto SparsePauliOp.
isa_observable1 = observable1.apply_layout(layout=chsh_isa_circuit.layout)
isa_observable2 = observable2.apply_layout(layout=chsh_isa_circuit.layout)
Paso 3: Ejecutar usando primitivas de Qiskit
Para ejecutar todo el experimento en una sola llamada a Estimator.
Podemos crear una primitiva Estimator de Qiskit Runtime para calcular nuestros valores esperados. El método EstimatorV2.run() toma un iterable de bloques unificados primitivos (PUBs). Cada PUB es un iterable en el formato (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()
Paso 4: Post-procesar y devolver el resultado en el formato clásico deseado
El estimador devuelve valores esperados para ambos observables, y .
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()
En la figura, las líneas y áreas grises delimitan los límites; las líneas más externas (de puntos y rayas) delimitan los límites cuánticos (), mientras que las líneas internas (discontinuas) delimitan los límites clásicos (). Puede ver que hay regiones donde las cantidades testigo CHSH exceden los límites clásicos. ¡Felicitaciones! ¡Ha demostrado exitosamente la violación de la desigualdad CHSH en un sistema cuántico real!
Encuesta del tutorial
Por favor, responda esta breve encuesta para proporcionar comentarios sobre este tutorial. Sus opiniones nos ayudarán a mejorar nuestras ofertas de contenido y experiencia de usuario.