Simulación exacta y ruidosa con primitivas de Qiskit Aer
Versiones de paquetes
El código de esta página fue desarrollado usando los siguientes requisitos. Recomendamos usar estas versiones o más recientes.
qiskit[all]~=2.3.0
qiskit-aer~=0.17
La simulación exacta con primitivas de Qiskit muestra cómo usar las primitivas de referencia incluidas en Qiskit para realizar simulaciones exactas de circuitos cuánticos. Los procesadores cuánticos actuales sufren de errores, o ruido, por lo que los resultados de una simulación exacta no necesariamente reflejan los resultados que obtendrías al ejecutar circuitos en hardware real. Si bien las primitivas de referencia en Qiskit no admiten el modelado de ruido, Qiskit Aer incluye implementaciones de las primitivas que sí lo admiten. Qiskit Aer es un simulador de circuitos cuánticos de alto rendimiento que puedes usar en lugar de las primitivas de referencia para obtener mejor rendimiento y más funcionalidades. Es parte del Ecosistema de Qiskit. En este artículo, demostramos el uso de las primitivas de Qiskit Aer para simulaciones exactas y ruidosas.
- Se requiere
qiskit-aerv0.14 o posterior. - Si bien las primitivas de Qiskit Aer implementan las interfaces de primitivas, no ofrecen las mismas opciones que las primitivas de Qiskit Runtime. El nivel de resiliencia, por ejemplo, no está disponible con las primitivas de Qiskit Aer.
- Consulta la documentación de AerSimulator para obtener detalles sobre las opciones del método de simulación que admite Aer.
Para explorar la simulación exacta y ruidosa, crea un circuito de ejemplo con ocho qubits:
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-aer
from qiskit.circuit.library import efficient_su2
n_qubits = 8
circuit = efficient_su2(n_qubits)
circuit.draw("mpl")
Este circuito contiene parámetros que representan los ángulos de rotación de las compuertas y . Al simular este circuito, necesitamos especificar valores explícitos para estos parámetros. En la siguiente celda, especificamos algunos valores para estos parámetros y usamos la primitiva Estimator de Qiskit Aer para calcular el valor de expectación exacto del observable .
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_aer import AerSimulator
from qiskit_aer.primitives import EstimatorV2 as Estimator
observable = SparsePauliOp("Z" * n_qubits)
params = [0.1] * circuit.num_parameters
exact_estimator = Estimator()
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(3, AerSimulator())
isa_circuit = pass_manager.run(circuit)
pub = (isa_circuit, observable, params)
job = exact_estimator.run([pub])
result = job.result()
pub_result = result[0]
exact_value = float(pub_result.data.evs)
exact_value
0.8870140234256602
Ahora, inicialicemos un modelo de ruido que incluya un error de despolarización del 2% en cada compuerta CX. En la práctica, el error que proviene de las compuertas de dos qubits, que aquí son compuertas CX, es la fuente de error dominante al ejecutar un circuito. Consulta Construir modelos de ruido para una descripción general de cómo construir modelos de ruido en Qiskit Aer.
En la siguiente celda, construimos un Estimator que incorpora este modelo de ruido y lo usamos para calcular el valor de expectación del observable.
from qiskit_aer.noise import NoiseModel, depolarizing_error
noise_model = NoiseModel()
cx_depolarizing_prob = 0.02
noise_model.add_all_qubit_quantum_error(
depolarizing_error(cx_depolarizing_prob, 2), ["cx"]
)
noisy_estimator = Estimator(
options=dict(backend_options=dict(noise_model=noise_model))
)
job = noisy_estimator.run([pub])
result = job.result()
pub_result = result[0]
noisy_value = float(pub_result.data.evs)
noisy_value
0.7247404214143528
Como puedes ver, el valor de expectación en presencia de ruido está bastante lejos del valor correcto. En la práctica, puedes emplear una variedad de técnicas de mitigación de errores para contrarrestar los efectos del ruido, pero una discusión de estas técnicas está fuera del alcance de este artículo.
Para tener una idea muy aproximada de cómo el ruido afecta el resultado final, considera nuestro modelo de ruido, que agrega un error de despolarización del 2% a cada compuerta CX. El error de despolarización con probabilidad se define como un canal cuántico que tiene la siguiente acción sobre una matriz de densidad :
donde es el número de qubits, en este caso, 2. Es decir, con probabilidad , el estado se reemplaza con el estado completamente mezclado, y el estado se preserva con probabilidad . Después de aplicaciones del canal de despolarización, la probabilidad de que el estado se preserve sería . Por lo tanto, esperamos que la probabilidad de retener el estado correcto al final de la simulación disminuya exponencialmente con el número de compuertas CX en nuestro circuito.
Contemos el número de compuertas CX en nuestro circuito y calculemos . Llamamos a count_ops para obtener un diccionario que mapea nombres de compuertas a conteos, y recuperamos la entrada para la compuerta CX.
cx_count = circuit.count_ops()["cx"]
(1 - cx_depolarizing_prob) ** cx_count
0.6542558123199923
Este valor, 65%, da una estimación aproximada de la probabilidad de que nuestro estado final sea correcto. Es una estimación conservadora porque no toma en cuenta el estado inicial de la simulación.
La siguiente celda de código muestra cómo usar la primitiva Sampler de Qiskit Aer para muestrear del circuito ruidoso. Necesitamos agregar mediciones al circuito antes de ejecutarlo con la primitiva Sampler.
from qiskit_aer.primitives import SamplerV2 as Sampler
measured_circuit = circuit.copy()
measured_circuit.measure_all()
noisy_sampler = Sampler(
options=dict(backend_options=dict(noise_model=noise_model))
)
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(3, AerSimulator())
isa_circuit = pass_manager.run(measured_circuit)
pub = (isa_circuit, params, 100)
job = noisy_sampler.run([pub])
result = job.result()
pub_result = result[0]
pub_result.data.meas.get_counts()
{'00100000': 1,
'00000000': 65,
'10101000': 1,
'10000000': 5,
'00001000': 1,
'00000110': 2,
'11110010': 1,
'00000011': 3,
'01010000': 3,
'11000000': 3,
'01111000': 1,
'01000000': 2,
'00000010': 1,
'01100000': 1,
'00011000': 1,
'00111100': 1,
'00010100': 1,
'00001111': 1,
'00110000': 1,
'01100101': 1,
'00000100': 1,
'10100000': 1,
'00000001': 1,
'11010000': 1}
Próximos pasos
- Para simular circuitos pequeños y sencillos, consulta Simulación exacta con primitivas de Qiskit.
- Revisa la documentación de Qiskit Aer.