Simulación exacta y ruidosa con primitivas Qiskit Aer
El código de esta página se ha desarrollado teniendo en cuenta los siguientes requisitos. Recomendamos utilizar estas versiones o versiones más recientes.
qiskit[all]~=2.5.2 qiskit-aer~=0.17
La simulación exacta con primitivas de « Qiskit SDK » muestra cómo utilizar las primitivas de referencia incluidas en Qiskit para realizar una simulación exacta de circuitos cuánticos. Los procesadores cuánticos actuales adolecen de errores, o ruido, por lo que los resultados de una simulación exacta no reflejan necesariamente los resultados que cabría esperar al ejecutar circuitos en hardware real. Aunque las primitivas de referencia de Qiskit no admiten la modelización del ruido, Qiskit Aer incluye implementaciones de las primitivas que sí admiten dicha modelización. Qiskit Aer es un simulador de circuitos cuánticos de alto rendimiento que puedes utilizar en lugar de las primitivas de referencia para obtener un mejor rendimiento y más funciones. Forma parte del ecosistema de Qiskit. En este artículo, mostramos cómo utilizar las primitivas de Qiskit Aer para la simulación exacta y con ruido.
qiskit-aerv0.14 o posterior.- Aunque las primitivas de Qiskit Aer implementan las interfaces de primitivas, no ofrecen las mismas opciones que las primitivas de « IBM Quantum ». El nivel de resiliencia, por ejemplo, no está disponible con las primitivas de Qiskit Aer.
- Consulte la documentación de AerSimulator para obtener más información sobre las opciones de métodos de simulación que admite Aer.
Para explorar la simulación exacta y ruidosa, crea un circuito de ejemplo con ocho qubits:
from qiskit.circuit.library import efficient_su2
n_qubits = 8
circuit = efficient_su2(n_qubits)
circuit.draw("mpl")Output:
Este circuito contiene parámetros para representar 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 utilizamos la primitiva Estimator de Qiskit Aer para calcular el valor exacto de la expectativa 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_valueOutput:
0.8870140234256602
Ahora, inicialicemos un modelo de ruido que incluya un error de despolarización del 2 % en cada puerta CX. En la práctica, los errores derivados de las puertas de dos qubits —en este caso, las puertas CX— son la principal fuente de error al ejecutar un circuito. Consulte «Creación de modelos de ruido» para obtener una descripción general sobre cómo construir modelos de ruido en Qiskit Aer.
En la siguiente celda, construimos un Estimador que incorpora este modelo de ruido y lo utilizamos para calcular el valor de la expectativa 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_valueOutput:
0.7247404214143528
Como se puede ver, el valor de la expectativa en presencia del ruido está bastante lejos del valor correcto. En la práctica, se pueden emplear diversas técnicas de mitigación de errores para contrarrestar los efectos del ruido, pero un análisis de estas técnicas queda fuera del alcance de este artículo.
Para hacernos una idea muy aproximada de cómo afecta el ruido al resultado final, consideremos nuestro modelo de ruido, que añade un error de despolarización del 2% a cada puerta CX. El error despolarizante 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 sustituye por el estado completamente mezclado, y el estado se conserva con probabilidad . Después de aplicaciones del canal despolarizante, la probabilidad de que el estado se conserve sería . Por lo tanto, esperamos que la probabilidad de conservar el estado correcto al final de la simulación disminuya exponencialmente con el número de puertas CX de nuestro circuito.
Contemos el número de puertas CX en nuestro circuito y calculemos . Llamamos a count_ops para obtener un diccionario que relaciona los nombres de las puertas con los recuentos, y recuperamos la entrada de la puerta CX.
cx_count = circuit.count_ops()["cx"]
(1 - cx_depolarizing_prob) ** cx_countOutput:
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 tiene en cuenta el estado inicial de la simulación.
La siguiente celda de código muestra cómo utilizar la primitiva Sampler de Qiskit Aer para muestrear desde el circuito ruidoso. Tenemos que añadir medidas 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()Output:
{'00000110': 1,
'11100000': 1,
'00000000': 59,
'11000000': 3,
'11110000': 1,
'00010100': 1,
'00100000': 2,
'00000011': 3,
'00110010': 1,
'00110101': 1,
'00000101': 1,
'11000010': 1,
'10000000': 4,
'00110000': 1,
'01000000': 2,
'00010000': 2,
'00000100': 2,
'01010000': 1,
'00001000': 2,
'00011110': 1,
'00001010': 1,
'01111000': 1,
'10100000': 1,
'01100000': 1,
'00001100': 2,
'00010110': 1,
'01001000': 1,
'00101000': 1,
'00000010': 1}
Próximos pasos
- Para simular circuitos pequeños y sencillos, consulta «Simulación exacta con primitivas de Qiskit SDK ».
- Revise la documentación de Qiskit Aer.