Explorando la incertidumbre
Para este módulo de Qiskit en las aulas, los estudiantes deben tener un entorno Python en funcionamiento con los siguientes paquetes instalados:
qiskitv2.1.0 o más recienteqiskit-ibm-runtimev0.40.1 o más recienteqiskit-aerv0.17.0 o más recienteqiskit.visualizationnumpypylatexenc
Para configurar e instalar los paquetes anteriores, consulta la guía Instalar Qiskit. Para ejecutar trabajos en ordenadores cuánticos reales, los estudiantes deberán crear una cuenta en IBM Quantum® siguiendo los pasos de la guía Configure su cuenta IBM Cloud.
Este módulo fue probado y utilizó 8 minutos de tiempo QPU. Esto es sólo una estimación. Su uso real puede variar. Dos cálculos que requieren mucho tiempo están marcados como tales en los comentarios de la cabecera y pueden realizarse en simuladores si los estudiantes no disponen de mucho tiempo en la QPU. Una vez eliminados, el módulo sólo requiere 30 segundos de QPU.
# Uncomment and modify this line as needed to install dependencies
#!pip install 'qiskit>=2.1.0' 'qiskit-ibm-runtime>=0.40.1' 'qiskit-aer>=0.17.0' 'numpy' 'pylatexenc'Vea el tutorial del módulo de la Dra. Katie McCormick a continuación, o haga clic aquí para verlo en YouTube.
Introducción
Probablemente haya oído hablar del principio de incertidumbre, incluso fuera de sus cursos de física. Un enunciado coloquial común de la incertidumbre es "Al mirar algo, influyes en ello" Eso es cierto. Pero una forma más física de describir la incertidumbre es que hay ciertos observables físicos que tienen una incompatibilidad que impide que ambos sean conocidos simultáneamente con una precisión arbitraria. Muchos estudiantes se encuentran primero con el par de variables incompatibles y , que significan la posición a lo largo de un eje llamado eje , y el momento lineal a lo largo de esa dirección, respectivamente. Para esas variables la restricción de incertidumbre se escribe Aquí, se denomina "incertidumbre en ", que tiene la misma definición que la desviación típica en estadística, y puede definirse como se define de la misma manera. Aquí no derivaremos esta relación de incertidumbre; señalaremos que es coherente con nuestra comprensión de las ondas clásicas. Es decir, una onda con una frecuencia realmente perfecta y una longitud de onda continuaría eternamente como una sinusoide perfecta. Mecánicamente cuántico, esto correspondería a conocer perfectamente el momento según la hipótesis de de Broglie: . Pero para conocer una partícula ondulatoria, la onda que la describe debe tener un pico más agudo en el espacio, como una gaussiana muy estrecha, por ejemplo. Sabemos que podemos expresar cualquier función continua, incluidas las funciones de onda con picos tan pronunciados, como una serie de Fourier de funciones sinusoidales con diferentes longitudes de onda. Pero a medida que la función de onda alcanza picos más agudos (y se conoce mejor la posición), necesitaremos más términos en la serie de Fourier, lo que significa una mezcla de más longitudes de onda (y por tanto, desde el punto de vista de la mecánica cuántica, más valores de momento).
Dicho de forma más sencilla: un estado con un momento bien definido (una sinusoide perfecta en el espacio) tiene una posición muy incierta. Un estado con una posición bien definida (como una distribución delta de Dirac) tiene un momento muy incierto.
Hay otras variables que muestran esa incompatibilidad. Por ejemplo, el espín de una partícula puede tener una proyección bien definida a lo largo de un eje, pero entonces no sabemos nada sobre la proyección en un eje ortogonal. Por ejemplo, el estado (para un qubit o una partícula spin-1/2 ) tiene una proyección definida a lo largo del eje (de 1 en el contexto de un qubit, y de en el contexto de una partícula spin-1/2 ). Pero este estado puede escribirse como una superposición de dos estados, cada uno de los cuales tiene una proyección bien definida sobre el eje : o equivalentemente tiene una proyección bien definida sobre , al igual que . Por lo tanto, si especificamos la proyección de un estado a lo largo del eje , no conocemos la proyección a lo largo del eje . Y si especificamos la proyección sobre el eje , no conocemos la proyección a lo largo de . Hay pequeñas diferencias cuando se habla de esto en el contexto del espín y en los qubits. Pero, en general, los estados propios de las matrices de Pauli tienen una relación interesante que podemos explorar. A lo largo de esta lección, comprobaremos experimentalmente nuestra intuición para la incertidumbre en estas variables incompatibles, y verificaremos que las relaciones de incertidumbre se mantienen en IBM® quantum computers.
Simple comprobación de la intuición
En este primer experimento y a lo largo de todo el módulo, utilizaremos un marco para la computación cuántica conocido como "patrones Qiskit", que divide los flujos de trabajo en los siguientes pasos:
- Paso 1: Asignar entradas clásicas a un problema cuántico
- Paso 2: Optimizar el problema para la ejecución cuántica
- Paso 3: Ejecutar utilizando Qiskit Runtime Primitives
- Etapa 4: Tratamiento posterior y análisis clásico
Por lo general, seguiremos estos pasos, aunque no siempre los etiquetemos explícitamente.
Empecemos cargando algunos paquetes necesarios, incluidas las primitivas Runtime. También seleccionaremos el ordenador cuántico menos ocupado de que dispongamos.
A continuación encontrará un código para guardar sus credenciales la primera vez que las utilice. Asegúrate de borrar esta información del cuaderno después de guardarlo en tu entorno, para que tus credenciales no se compartan accidentalmente cuando compartas el cuaderno. Consulte Configurar su cuenta IBM Cloud e Inicializar el servicio en un entorno no fiable para obtener más orientación.
from numpy import pi
# Load the Qiskit Runtime service
from qiskit_ibm_runtime import QiskitRuntimeService
# Syntax for first saving your token. Delete these lines after saving your credentials.
# QiskitRuntimeService.save_account(channel='ibm_quantum_platform',
# instance = '<YOUR_IBM_INSTANCE_CRN>', token='<YOUR-API_KEY>', overwrite=True, set_as_default=True)
# service = QiskitRuntimeService(channel='ibm_quantum_platform')
# Load saved credentials
service = QiskitRuntimeService()# Load the Runtime primitive and session
from qiskit_ibm_runtime import (
Batch,
SamplerV2 as Sampler,
EstimatorV2 as Estimator,
)
# Use the least busy backend
backend = service.least_busy(min_num_qubits=127)
print(backend.name)Output:
ibm_sherbrooke
Si un estudiante agota su tiempo disponible de computación cuántica durante la lección, las líneas de abajo pueden ser des-comentadas y usadas para configurar un simulador que imite parcialmente el comportamiento del ruido del ordenador cuántico seleccionado arriba.
# Import an estimator, this time from qiskit (we will import from Runtime for real hardware)
from qiskit_aer.primitives import SamplerV2, EstimatorV2
from qiskit_aer.noise import NoiseModel
# Generate the noise model from the backend properties
noise_model = NoiseModel.from_backend(backend)
noisy_sampler = SamplerV2(options={"backend_options": {"noise_model": noise_model}})
noisy_estimator = EstimatorV2(options={"backend_options": {"noise_model": noise_model}})Recordemos que un estado propio de un operador, Z, no es un estado propio de otro operador X. Lo observaremos ahora, experimentalmente haciendo mediciones a lo largo de los ejes y . Para medir a lo largo de , simplemente utilizamos qc.measure (), porque los ordenadores cuánticos IBM están estructurados para medir a lo largo de . Pero para medir a lo largo de , debemos rotar el sistema para mover efectivamente el eje hasta la orientación a lo largo de la cual medimos. Esto se consigue con una puerta Hadamard. Se requiere un paso similar para las mediciones a lo largo de . Los pasos necesarios se recogen aquí por comodidad:
- Para medir a lo largo de :
qc.measure() - Para medir a lo largo de :
qc.h()entoncesqc.measure() - Para medir a lo largo de :
qc.sdg(),qc.h(),qc.sentoncesqc.measure()
Paso 1: Asignar entradas clásicas a un problema cuántico
En este caso, el paso de mapeo consiste simplemente en expresar las mediciones y rotaciones descritas anteriormente en un circuito cuántico:
# Step 1: Map
# Import some general packages
from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(2, "c")
qc = QuantumCircuit(qr, cr)
# Add a first measurement
qc.measure(qr, cr[0])
qc.barrier()
# Change basis so that measurements made on quantum computer which normally tell us about z,
# now tell us about x.
qc.h(qr)
# Add a second measurement
qc.measure(qr, cr[1])
qc.draw("mpl")Output:
Paso 2: Optimizar el problema para la ejecución cuántica
Este paso toma las operaciones que queremos realizar y las expresa en términos de la funcionalidad de un ordenador cuántico específico. También mapea nuestro problema en el diseño del ordenador cuántico.
# Step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)Paso 3: Ejecutar utilizando primitivas de Qiskit Runtime
Podemos utilizar el muestreador para recopilar datos estadísticos sobre las mediciones. Crearemos la primitiva Sampler para que se ejecute en un ordenador cuántico real utilizando mode = backend. Existen otros modos para otros flujos de trabajo, y a continuación utilizaremos uno de ellos. El Sampler se utilizará llamando a su método run() con una lista de «pubs» (Primitive Unified Blocs). Cada entrada contiene hasta tres valores que, en conjunto, definen una unidad de trabajo de cálculo que debe completar el estimador: circuitos, observables y parámetros. También puedes proporcionar una lista de circuitos, una lista de variables observables y una lista de parámetros. Para obtener más información, consulta la Descripción general de los PUB.
Queremos ejecutarlo en un ordenador cuántico real, de modo que estemos llevando a cabo un experimento de física cuántica real. Si agota el tiempo asignado a los ordenadores cuánticos reales, puede comentar el código siguiente para el ordenador cuántico y descomentar el código para ejecutarlo en un simulador.
# Step 3: Run the job on a real quantum computer
sampler = Sampler(mode=backend)
pubs = [qc_isa]
job = sampler.run(pubs)
res = job.result()
counts = res[0].data.c.get_counts()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_sampler.run([qc_isa])
# res=job.result()
# counts=res[0].data.c.get_counts()Paso 4: Postprocesamiento
Se trata de un caso especialmente sencillo de postprocesamiento, en el que simplemente visualizamos los recuentos.
Ten en cuenta que Qiskit ordena los qubits, las medidas y otras cosas enumerando el elemento con el número más bajo en último lugar / a la derecha, una convención denominada "little-endian". Esto significa que la columna "10" se refiere a los recuentos en los que la primera medición dio un "0" y la segunda un "1".
# Step 4: Post-process
from qiskit.visualization import plot_histogram
plot_histogram(counts)Output:
Si esta convención no le resulta atractiva, puede utilizar marginal_counts para visualizar los resultados de cada medición por separado:
from qiskit.result import marginal_counts
plot_histogram(
marginal_counts(counts, indices=[0]), title="Counts after first measurement"
)Output:
plot_histogram(
marginal_counts(counts, indices=[1]), title="Counts after second measurement"
)Output:
Por defecto, los estados en Qiskit se inicializan al estado . Así pues, no es de extrañar que casi todas las primeras mediciones dieran . Nótese, sin embargo, que en la segunda medición (la que da información sobre las proyecciones del estado en ) hubo casi un empate. Parece que este estado que nos da un resultado muy predecible de las mediciones a lo largo de nos da un conjunto muy impredecible de resultados para las mediciones a lo largo de . Exploremos esto.
¿Qué ocurre si se realizan las mediciones en orden inverso? Podríamos empezar utilizando la puerta de Hadamard para obtener estadísticas sobre la probabilidad de que se mida en . Luego, para la segunda medición, cambiaremos de nuevo a la base utilizando una segunda puerta de Hadamard.
# Step 1:
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(2, "c")
qc = QuantumCircuit(qr, cr)
# Change basis to measure along x.
qc.h(qr)
qc.measure(qr, cr[0])
qc.barrier()
# Change our basis back to z and make a second measurement
qc.h(qr)
qc.measure(qr, cr[1])
qc.draw("mpl")Output:
# Step 2: Transpile the circuit for running on a quantum computer
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)# Step 3: Run the job on a real quantum computer
sampler = Sampler(mode=backend)
pubs = [qc_isa]
job = sampler.run(pubs)
res = job.result()
counts = res[0].data.c.get_counts()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_sampler.run([qc_isa])
# res=job.result()
# counts=res[0].data.c.get_counts()# Step 4: Post-process
from qiskit.visualization import plot_histogram
plot_histogram(counts)Output:
Aquí, ¡parece que tenemos aún menos previsibilidad! Antes, al menos sabíamos cuál sería el resultado de la primera medición, ahora tenemos una distribución bastante uniforme entre todos los estados posibles. No es difícil entender por qué ha sucedido esto. Empezamos en , que es una mezcla 50-50 de y , según Así que claramente debería haber la misma probabilidad de obtener el estado + o - (asignados a 0 y 1 en el gráfico) para la primera medición. La medición a lo largo de colapsa el estado en un estado propio o en el estado propio . Cada uno de estos estados es una mezcla 50-50 de y , según Por lo tanto, una vez que el sistema se encuentra en un estado propio de , es evidente que las mediciones a lo largo de producirán tanto como , y lo harán con aproximadamente la misma probabilidad. Así, nuestro primer ejemplo nos mostró que algunos estados tendrán resultados muy predecibles de algunas mediciones, pero resultados impredecibles para otras mediciones. El ejemplo actual nos demuestra que podemos hacerlo peor. Hay estados que pueden darnos resultados impredecibles para ambas mediciones, incluso si todo lo que hacemos es intercambiar el orden de las mediciones. Investiguemos lo cierta o incierta que es una cantidad para un estado determinado.
Cálculo de la incertidumbre
Podemos cuantificarlo utilizando la incertidumbre, o varianza. La "incertidumbre" suele definirse como la raíz cuadrada de la "varianza" de una distribución. Es decir, la incertidumbre para algún observable se denota y viene dada por
Para el caso de las matrices de Pauli, para las que , esto se convierte en
Apliquemos esto a un ejemplo concreto. Empecemos con el estado y determinemos la incertidumbre del observable en ese estado.
Comprueba tu comprensión
Calcule la incertidumbre de en el estado , a mano.
En el estado dado, esto produce:
Podemos crear un estado inicial arbitrario utilizando qc.initialize(). Tenga en cuenta que la sintaxis para la unidad imaginaria aquí es .
# Step 1: Map the problem into a quantum circuit
from qiskit.quantum_info import SparsePauliOp
import numpy as np
obs = SparsePauliOp("X")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Initialize the state
qc.initialize([1, 1j] / np.sqrt(2))
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs_isa = obs.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
estimator = Estimator(mode=backend)
pubs = [(qc_isa, obs_isa)]
job = estimator.run([[qc_isa, obs_isa]])
res = job.result()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([[qc_isa,obs_isa]])
# res=job.result()
# Step 4: Return the result in classical form, and analyze.
print(res[0].data.evs)Output:
-0.02408454165642664
Según nuestra ecuación anterior, Vamos a seguir con el mismo estado, pero encontrar el valor de la expectativa de , ahora:
# Step 1: Map the problem into a quantum circuit
obs = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Initialize the state to |+>_y
qc.initialize([1, 1j] / np.sqrt(2))
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs_isa = obs.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
estimator = Estimator(mode=backend)
pubs = [(qc_isa, obs_isa)]
job = estimator.run(pubs)
res = job.result()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([[qc_isa,obs_isa]])
# res=job.result()
# Step 4: Return the result in classical form, and analyze.
print(res[0].data.evs)Output:
0.04958271968581247
Podríamos hacer los mismos cálculos que antes, pero veríamos que la varianza vuelve a estar muy próxima a 1.0. Podríamos concluir que . De hecho, esto es aproximadamente correcto para el estado que elegimos. Pero, ¿podemos hacerlo mejor? ¿O peor?
Recordemos que existe una relación de incertidumbre entre la posición a lo largo de una dirección, y el momento a lo largo de la misma dirección, . Para esas variables, pero la forma más familiar es probablemente Si esto es todo lo que recordamos, podríamos sentirnos tentados a pensar que y también podrían tener un límite de incertidumbre tan fundamental. ¿Quizás es imposible que el producto llegue a cero? Probemos con otro estado y veamos si esto se mantiene. Esta vez, utilizaremos . Veamos qué ocurre. Tenga en cuenta que en el código siguiente, el estimador puede aceptar dos conjuntos de circuitos y observables en el mismo envío de trabajo.
# Step 1: Map the problem into a quantum circuit
obs1 = SparsePauliOp("X")
obs2 = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Initialize the state
qc.initialize([1, 1] / np.sqrt(2))
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs1_isa = obs1.apply_layout(layout=qc_isa.layout)
obs2_isa = obs2.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
pubs = [(qc_isa, obs1_isa), (qc_isa, obs2_isa)]
job = estimator.run(pubs)
res = job.result()
batch.close()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([[qc,obs1],[qc,obs2]])
# res=job.result()
# Step 4: Return the result in classical form, and analyze.
print("The expectation value of the first observable is: ", res[0].data.evs)
print("The expectation value of the second observable is: ", res[1].data.evs)Output:
The expectation value of the first observable is: 1.0011036174126302
The expectation value of the second observable is: 0.0029429797670141016
El valor esperado de debe ser cercano a 1.0, pero no debe superar 1.0. No te preocupes si supera 1.0 por muy poco. Esto puede atribuirse a factores como el ruido y/o el error de lectura. Aunque se trata de un tema muy importante, podemos ignorarlo por ahora.
Obtuvimos un valor esperado de muy próximo a 1.0 (lo que corresponde a una varianza muy baja para ). Esto hace que el producto de las dos varianzas sea bastante bajo:
Aunque no es exactamente cero, este valor se hace pequeño en comparación con los valores propios de los operadores de Pauli ( ). Bien, puede que recuerdes que la relación de incertidumbre entre la posición lineal y el momento podría escribirse de otra manera, utilizando explícitamente la relación de conmutación entre los operadores y :
donde
es el conmutador de y .
Esta es la forma que puede extenderse más fácilmente a los operadores de Pauli. En general, para dos operadores y ,
Y en el caso de las matrices de Pauli y , necesitamos para calcular
Mostramos esto aquí, y dejamos cálculos similares al lector como ejercicio:
Esta es una respuesta perfectamente aceptable, pero con un paso más, vemos
Nuestra relación de incertidumbre se convierte así en
Comprueba tu comprensión
Determine y . Use esto para escribir las relaciones de incertidumbre entre & , y & .
Combinando con la relación general de incertidumbre, tenemos
Verificar la coherencia
Antes de seguir adelante, comprobemos que esto concuerda con nuestra constatación anterior. Usamos el estado Y encontramos que Ahora sabemos que este producto debe ser mayor o igual a
Así es,
Utilice las preguntas siguientes para intuir estas conclusiones:
Comprueba tu comprensión
Responde a los siguientes puntos en conjunto:
(a) ¿Qué estados esperarías que tuvieran incertidumbre cero en ?
(b) ¿Qué estados esperarías que tuvieran incertidumbre cero en ?
(c) ¿En qué estados se obtendría un valor de expectativa cero ?
(d) ¿Son coherentes las respuestas a las preguntas anteriores con el caso ?
(e) Escribe código para comprobarlo explícitamente utilizando el estimador.
(a) Podríamos esperar que los estados propios del operador produjeran una incertidumbre cero en . De hecho, utilizando tenemos
(b) Podríamos esperar que los estados propios del operador produjeran una incertidumbre cero en . De hecho, utilizando tenemos
(c) Esperamos encontrar para cualquier estado que, cuando se mide, da una proyección positiva en el eje con la misma frecuencia que una proyección negativa. Se trata de los estados propios de y .
(d) Sí. Cabría esperar un valor muy pequeño del producto de incertidumbres para los estados propios de o : Esto puede sostenerse porque también esperaríamos para esos mismos estados. Por tanto, la relación de incertidumbre podría satisfacerse.
(e) Un código como el siguiente lo verificaría:
obs1 = SparsePauliOp.from_list( [("X", 1.000)] ) obs2 = SparsePauliOp.from_list( [("Y", 1.000)] ) obs3 = SparsePauliOp.from_list( [("Z", 1.000)] ) qc = QuantumCircuit(1,1) qc.ry(pi/2,0) job = estimator.run([(qc, [[obs1], [obs2], [obs3]])], precision=0.001) res=job.result()Donde los resultados devuelven todos los valores de las expectativas. Para recuperar todos los valores de las expectativas y calcular las incertidumbres, podríamos utilizar:
xs=res[0].data.evs[0] ys=abs(res[0].data.evs[1]) zs=res[0].data.evs[2] import math prodxz=((1-xs[i]*xs[i])**0.5)*(1-zs[i]*zs[i])**0.5
Responde a los siguientes puntos en conjunto:
(a) ¿Puede pensar en un estado en el que tendría un gran valor de expectativa ?
(b) ¿Esperaría que ese mismo estado tuviera una incertidumbre grande o pequeña en ?
(c) ¿Esperaría que ese mismo estado tuviera una incertidumbre grande o pequeña en ?
(d) ¿Son coherentes las respuestas a las preguntas anteriores con el caso ?
(e) Escribe código para comprobarlo explícitamente utilizando el estimador.
(a) Esperamos encontrar para el estado propio de : .
(b) Podríamos esperar que tuviera una gran incertidumbre en el estado ya que medir en ese estado daría un resultado positivo y negativo con la misma frecuencia/probabilidad.
(c) Podríamos esperar que tuviera una gran incertidumbre en el estado ya que medir en ese estado daría un resultado positivo y negativo con la misma frecuencia/probabilidad.
(d) Sí. Cabría esperar un valor grande para el producto de incertidumbres para los estados propios de y para en concreto. También esperaríamos para ese mismo estado. Así que tanto como son bastante grandes en este estado, y es plausible que la relación de incertidumbre pueda satisfacerse de nuevo.
(e) Un código como el siguiente lo verificaría:
obs1 = SparsePauliOp.from_list( [("X", 1.000)] ) obs2 = SparsePauliOp.from_list( [("Y", 1.000)] ) obs3 = SparsePauliOp.from_list( [("Z", 1.000)] ) qc = QuantumCircuit(1,1) qc.rx(-pi/2,0) job = estimator.run([(qc, [[obs1], [obs2], [obs3]])], precision=0.001) res=job.result()Donde los resultados devuelven todos los valores de las expectativas. Para recuperar todos los valores de las expectativas y calcular las incertidumbres, podríamos utilizar:
xs=res[0].data.evs[0] ys=abs(res[0].data.evs[1]) zs=res[0].data.evs[2] import math prodxz=((1-xs[i]*xs[i])**0.5)*(1-zs[i]*zs[i])**0.5
Relaciones de incertidumbre en las pruebas
La prueba anterior sólo ha demostrado la validez de la relación de incertidumbre para una única elección del vector de estado . Para convencernos de que, en general, es coherente con el experimento, deberíamos realizar cálculos similares utilizando el estimador para muchas elecciones del vector de estado. Empecemos girando nuestro vector de estado alejándolo del eje , utilizando una puerta RY para producir diferentes estados iniciales utilizando un parámetro .
# The calculation below uses approximately 3-4 minutes of QPU time.
# Step 1: Map the problem into a quantum circuit
from qiskit.circuit import Parameter
import numpy as np
# Specify observables
obs1 = SparsePauliOp("X")
obs2 = SparsePauliOp("Y")
obs3 = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Rotate away from |0>
theta = Parameter("θ")
qc.ry(theta, 0)
params = np.linspace(0, 2, num=21)
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs1_isa = obs1.apply_layout(layout=qc_isa.layout)
obs2_isa = obs2.apply_layout(layout=qc_isa.layout)
obs3_isa = obs3.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
pubs = [(qc_isa, [[obs1_isa], [obs2_isa], [obs3_isa]], [params])]
job = estimator.run(pubs, precision=0.01)
res = job.result()
batch.close()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([(qc, [[obs1], [obs2], [obs3]], [params])])
# res=job.result()# Step 4: Post-processing and classical analysis.
xs = res[0].data.evs[0]
ys = abs(res[0].data.evs[1])
zs = res[0].data.evs[2]
# Calculate uncertainties
delx = []
delz = []
prodxz = []
for i in range(len(xs)):
delx.append(abs((1 - xs[i] * xs[i])) ** 0.5)
delz.append(abs((1 - zs[i] * zs[i])) ** 0.5)
prodxz.append(delx[i] * delz[i])# Here we can plot the results from this simulation.
import matplotlib.pyplot as plt
plt.plot(params, delx, label=r"$\Delta$ X")
plt.plot(params, ys, label=r"$\langle$ Y $\rangle$")
plt.plot(params, delz, label=r"$\Delta$ Z")
plt.plot(params, prodxz, label=r"$\Delta$X $\Delta$Z")
plt.xlabel(r"$\theta$")
plt.ylabel("Expectation/Uncertainty Values")
plt.legend()
plt.show()Output:
Obsérvese que la curva roja es siempre mayor que la curva naranja A veces el producto de incertidumbre baja y se acerca algo al límite, y otras veces sube y se aleja del límite, pero siempre obedece a la relación de incertidumbre.
Por supuesto, ésta podría no ser la mejor prueba de la relación de incertidumbre, ya que nuestro límite está siempre muy próximo a cero. Utilicemos un estado cuántico que tenga una proyección mayor sobre los estados propios de . Concretamente, seguiremos rotando hacia abajo desde el eje en ángulos variables, pero ahora también rotaremos ese estado resultante alrededor de en algún ángulo, quizás , y veremos qué ocurre.
# The calculation below uses approximately 3-4 minutes of QPU time.
from qiskit.circuit import Parameter
import numpy as np
# Step 1: Map the problem to a quantum circuit
# Specify observables
obs1 = SparsePauliOp("X")
obs2 = SparsePauliOp("Y")
obs3 = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Rotate away from |0> along one plane, and then along a transverse direction.
theta = Parameter("θ")
qc.ry(theta, 0)
qc.rz(pi / 4, 0)
params = np.linspace(0, 2, num=21)
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs1_isa = obs1.apply_layout(layout=qc_isa.layout)
obs2_isa = obs2.apply_layout(layout=qc_isa.layout)
obs3_isa = obs3.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
pubs = [(qc_isa, [[obs1_isa], [obs2_isa], [obs3_isa]], [params])]
job = estimator.run(pubs, precision=0.01)
res = job.result()
batch.close()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([(qc, [[obs1], [obs2], [obs3]], [params])])
# res=job.result()# Step 4: Post-processing and classical analysis.
xs = res[0].data.evs[0]
ys = abs(res[0].data.evs[1])
zs = res[0].data.evs[2]
# Calculate uncertainties
delx = []
delz = []
prodxz = []
for i in range(len(xs)):
delx.append(abs((1 - xs[i] * xs[i])) ** 0.5)
delz.append(abs((1 - zs[i] * zs[i])) ** 0.5)
prodxz.append(delx[i] * delz[i])# Here we can plot the results from this simulation.
import matplotlib.pyplot as plt
plt.plot(params, delx, label=r"$\Delta$ X")
plt.plot(params, ys, label=r"$\langle$ Y $\rangle$")
plt.plot(params, delz, label=r"$\Delta$ Z")
plt.plot(params, prodxz, label=r"$\Delta$X $\Delta$Z")
plt.xlabel(r"$\theta$")
plt.ylabel("Expectation/Uncertainty Values")
plt.legend()
plt.show()Output:
Ahora vemos que el límite de la incertidumbre se está poniendo a prueba La curva roja se acerca mucho más a la curva naranja que antes. De hecho, en ausencia de ruido, la relación de incertidumbre estaría exactamente saturada ( ) en un punto. En presencia de ruido y error de lectura, no debería sorprender que una ejecución ocasionalmente arroje un resultado ligeramente superior a Esto no es una verdadera violación de la incertidumbre; es solo un artefacto del error distinto de cero.
Comprueba tu comprensión
Explica cómo llevarías esto al límite absoluto, haciendo que « » sea lo más grande posible.
El código actualmente tiene líneas que rotan el estado inicial por defecto , hacia abajo desde el eje por algún ángulo parametrizado y luego también alrededor del eje por un ángulo que rota el vector de estado parte del camino hacia el eje .
qc.ry(theta,0)qc.rz(pi/4,0)Podríamos cambiar la rotación alrededor de de a , rotando todo el camino hasta un estado propio de :
qc.ry(theta,0)qc.rz(pi/2,0)No sería necesario ningún otro cambio.
Cambia el código o cópialo e implementa esa comprobación de la relación de incertidumbre con el valor de expectativa de Y maximizado. ¿Se mantiene la relación de incertidumbre?
Utilizaríamos exactamente el código del ejemplo anterior, con
qc.rz(pi/2,0)sustituido por
qc.rz(pi/4,0).La figura resultante debería ser como la de abajo, y sí, el principio de incertidumbre debería seguir siendo válido.

Modifica el código anterior para hacer una imagen similar, demostrando que a partir de las medidas en el ordenador cuántico el producto se comporta como debería. Elige el conjunto de estados que quieras.
Utilizaríamos exactamente el código del ejemplo anterior, y de cara podríamos utilizar los mismos resultados de arriba, sólo que utilizando los valores de las expectativas para calcular las diferentes incertidumbres. Por ejemplo, podríamos utilizar
xs=res[0].data.evs[0] ys=res[0].data.evs[1] zs=abs(res[0].data.evs[2]) import math delx = [] dely = [] prodxy=[] for i in range(len(xs)): delx.append((1-xs[i]*xs[i])**0.5) dely.append((1-ys[i]*ys[i])**0.5) prodxy.append(((1-xs[i]*xs[i])**0.5)*(1-ys[i]*ys[i])**0.5)y podríamos trazar
import matplotlib.pyplot as plt plt.plot(params, delx, label=r'$\Delta$ X') plt.plot(params, dely, label=r'$\langle$ Y $\rangle$') plt.plot(params, zs, label=r'$\Delta$ Z') plt.plot(params, prodxy, label=r'$\Delta$X $\Delta$Z') plt.xlabel(r'$\theta$') plt.ylabel('Expectation/Uncertainty Values') plt.legend() plt.show()
Reto: Escribir código para escanear a través de muchos valores de , al igual que escaneamos a través de muchos valores de , y hacer un gráfico 3-D que muestre que la relación de incertidumbre nunca se viola. Elige los observables que quieras.
Preguntas
Los profesores pueden solicitar versiones de estos cuadernos con claves de respuestas y orientaciones sobre su colocación en planes de estudios comunes rellenando esta rápida encuesta sobre cómo se están utilizando los cuadernos.
Conceptos fundamentales:
- Existen relaciones de incertidumbre entre muchos conjuntos de observables físicos, incluyendo la posición y el momento lineal, y los componentes del espín.
- Las matrices de Pauli no conmutan. Se trata de un reflejo matemático del hecho de que no todos los componentes del espín pueden conocerse/determinarse simultáneamente.
- La computación cuántica hace un uso intensivo de los operadores/matrices de Pauli, por lo que resulta útil conocer la relación de incertidumbre de los operadores de Pauli, así como de los operadores de espín estrechamente relacionados.
- Una fórmula general para la incertidumbre de dos operadores y es
- Un estado propio de un operador da lugar a una incertidumbre nula en la observable física asociada a dicho operador. Incluso a nivel experimental,
- Un estado propio de algún operador producirá una incertidumbre mayor para un operador que no conmute con .
- Los resultados experimentales con un ordenador cuántico real confirman la intuición que obtenemos de las representaciones matriciales de los operadores físicos.
Preguntas de verdadero o falso:
- T/F Se puede medir simultáneamente y , pero no .
- T/F Se puede medir simultáneamente y , pero no .
- T/F Los operadores de posición lineal y de momento lineal no conmutan.
- T/F IBM los ordenadores cuánticos miden a lo largo de por defecto, por lo que se debe realizar una rotación para medir a lo largo de cualquier otra dirección.
- T/F El circuito de abajo mide efectivamente y luego .
Preguntas del moderador:
-
¿Cuál de las siguientes relaciones de incertidumbre se muestra en el siguiente diagrama?
- a.
- b.
- c.
- d. Ninguno de los anteriores
-
¿Cuál de las siguientes es la secuencia estándar para realizar una medición a lo largo de ?
- a. Sólo
qc.measure() - b.
qc.h()entoncesqc.measure() - c.
qc.h(),qc.h()entoncesqc.measure() - d.
qc.h(),qc.s,qc.h()entoncesqc.measure() - e.
qc.sdg(),qc.h(),qc.sentoncesqc.measure() - f.
qc.sdg(),qc.h(),qc.s,qc.h()entoncesqc.measure()
- a. Sólo
-
¿Cuál de los siguientes estados produce el mayor valor de expectativa ?
- a.
- b.
- c. también llamado
- d. también llamado
- e. también llamado
- f. también llamado
-
¿Cuál de los siguientes estados produce la mayor incertidumbre ?
- a.
- b. también llamado
- c. también llamado
- d. a y b están empatados
- decir, b y c están empatados
- f. a, b y c están empatados
Preguntas para el debate:
-
¿Este concepto de incertidumbre entra en conflicto de algún modo con la noción de espín como flecha vectorial en el espacio cartesiano? ¿Y en la esfera de Bloch?
-
Supongamos que orienta un dispositivo de medición a lo largo de una dirección a medio camino entre los ejes y . ¿Qué ocurre? ¿Puede hacer una medición en esta dirección? ¿Cómo se relaciona esto con la incertidumbre en y ?
-
¿Qué experimentos adicionales le gustaría hacer para convencerse de los resultados obtenidos aquí?