Nota
Esta página fue generada a partir de docs/tutorials/Error-Suppression-and-Error-Mitigation.ipynb.
Supresión y mitigación de errores con Qiskit Runtime¶
To illustrate the need for error suppression and mitigation, we will start by taking a look at some results without error suppression or error mitigation. After setting up our environment, we will use a noiseless simulator to get an idea of what ideal results look like. Next, we are going to run the same experiment in a real backend without using error suppression or error mitigation.
[ ]:
import datetime
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
plt.rcParams.update({"text.usetex": True})
plt.rcParams["figure.figsize"] = (6, 4)
mpl.rcParams["figure.dpi"] = 200
from qiskit_ibm_runtime import Estimator, Session, QiskitRuntimeService, Options
from qiskit.quantum_info import SparsePauliOp
from qiskit import QuantumCircuit
service = QiskitRuntimeService()
Crear un circuito Trotter¶
La siguiente celda de código define una lista de circuitos Trotter para usar en los experimentos.
[2]:
backend_simulator = "ibmq_qasm_simulator"
backend = "ibmq_montreal"
qubits = 4
trotter_layer = QuantumCircuit(qubits)
trotter_layer.rx(0.1, range(qubits))
trotter_layer.cx(0, 1)
trotter_layer.cx(2, 3)
trotter_layer.rz(-0.2, [1, 3])
trotter_layer.cx(0, 1)
trotter_layer.cx(2, 3)
trotter_layer.cx(1, 2)
trotter_layer.rz(-0.2, 2)
trotter_layer.cx(1, 2)
num_steps = 6
trotter_circuit_list = []
for i in range(1, num_steps):
trotter_circuit = QuantumCircuit(qubits)
for _ in range(i):
trotter_circuit = trotter_circuit.compose(trotter_layer)
trotter_circuit_list.append(trotter_circuit)
print(f"Trotter circuit with {i} Trotter steps")
display(trotter_circuit.draw(fold=-1))
obs = SparsePauliOp("Z" * qubits)
obs_list = [obs] * len(trotter_circuit_list)
Trotter circuit with 1 Trotter steps
┌─────────┐ q_0: ┤ Rx(0.1) ├──■────────────────■──────────────────────── ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐ q_1: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├──■────────────────■── ├─────────┤└───┘└──────────┘└───┘┌─┴─┐┌──────────┐┌─┴─┐ q_2: ┤ Rx(0.1) ├──■────────────────■──┤ X ├┤ Rz(-0.2) ├┤ X ├ ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐└───┘└──────────┘└───┘ q_3: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├────────────────────── └─────────┘└───┘└──────────┘└───┘
Trotter circuit with 2 Trotter steps
┌─────────┐ ┌─────────┐ q_0: ┤ Rx(0.1) ├──■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──────────────────────── ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐ q_1: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├──■────────────────■── ├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘┌─┴─┐┌──────────┐┌─┴─┐ q_2: ┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■──┤ X ├┤ Rz(-0.2) ├┤ X ├ ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐└───┘└──────────┘└───┘ q_3: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├────────────────────── └─────────┘└───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘
Trotter circuit with 3 Trotter steps
┌─────────┐ ┌─────────┐ ┌─────────┐ q_0: ┤ Rx(0.1) ├──■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──────────────────────── ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐ q_1: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├──■────────────────■── ├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘┌─┴─┐┌──────────┐┌─┴─┐ q_2: ┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■──┤ X ├┤ Rz(-0.2) ├┤ X ├ ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐└───┘└──────────┘└───┘ q_3: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├────────────────────── └─────────┘└───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘
Trotter circuit with 4 Trotter steps
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ q_0: ┤ Rx(0.1) ├──■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──────────────────────── ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐ q_1: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├──■────────────────■── ├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘┌─┴─┐┌──────────┐┌─┴─┐ q_2: ┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■──┤ X ├┤ Rz(-0.2) ├┤ X ├ ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐└───┘└──────────┘└───┘ q_3: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├────────────────────── └─────────┘└───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘
Trotter circuit with 5 Trotter steps
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ q_0: ┤ Rx(0.1) ├──■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──────────────────────── ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐ q_1: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├──■────────────────■── ├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘┌─┴─┐┌──────────┐┌─┴─┐ q_2: ┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■──┤ X ├┤ Rz(-0.2) ├┤ X ├ ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐└───┘└──────────┘└───┘ q_3: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├────────────────────── └─────────┘└───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘
Ejecución del simulador¶
[4]:
options = Options()
options.execution.shots = 1000
options.optimization_level = 0 # No optimization
options.resilience_level = 0 # No mitigation
with Session(service=service, backend=backend_simulator) as session:
estimator_sim = Estimator(session=session, options=options)
job_sim = estimator_sim.run(circuits=trotter_circuit_list, observables=obs_list)
print("job id:", job_sim.job_id)
print(job_sim.result())
expvals_ideal = job_sim.result().values
expvals_ideal_variance = [
metadata["variance"] / metadata["shots"] for metadata in job_sim.result().metadata
]
std_error_ideal = np.sqrt(expvals_ideal_variance)
job id: cdkrpbpg1234sbmtrt3g
EstimatorResult(values=array([0.98 , 0.926, 0.872, 0.796, 0.68 ]), metadata=[{'variance': 0.03960000000000008, 'shots': 1000}, {'variance': 0.14252399999999987, 'shots': 1000}, {'variance': 0.23961600000000005, 'shots': 1000}, {'variance': 0.36638399999999993, 'shots': 1000}, {'variance': 0.5375999999999999, 'shots': 1000}])
No mitigado, backend real¶
[5]:
options = Options()
options.execution.shots = 1000
options.optimization_level = 0 # No optimization
options.resilience_level = 0 # No error mitigation
with Session(service=service, backend=backend) as session:
estimator = Estimator(session=session, options=options)
job = estimator.run(circuits=trotter_circuit_list, observables=obs_list)
print("job id:", job.job_id)
print(job.result())
expvals_unmit = job.result().values
expvals_unmit_variance = [
metadata["variance"] / metadata["shots"] for metadata in job.result().metadata
]
std_error_unmit = np.sqrt(expvals_unmit_variance)
job id: cdkrpeaan60ka16e8340
EstimatorResult(values=array([0.786, 0.74 , 0.636, 0.562, 0.446]), metadata=[{'variance': 0.382204, 'shots': 1000}, {'variance': 0.4524, 'shots': 1000}, {'variance': 0.595504, 'shots': 1000}, {'variance': 0.684156, 'shots': 1000}, {'variance': 0.801084, 'shots': 1000}])
Teoría y antecedentes¶
IBM Quantum¶
Queremos construir una herramienta que, a partir de 2024, sea capaz de estimar observables sin ruido de circuitos de 100 qubits, con profundidad de 100, en un día.
Aunque esto no es una promesa de ventaja cuántica per-se, el objetivo es llegar al punto en el que podamos resolver problemas interesantes o relevantes de forma más rápida, precisa o económica en un marco de tiempo práctico en comparación con los cálculos clásicos eficientes.
El umbral de simulabilidad parece estar en torno a los 100 qubits. Sin embargo, estos no son suficientes qubits, ya que también necesitamos un circuito cuántico lo suficientemente complejo para garantizar que no se pueda reproducir de forma clásica. Por ejemplo, profundo, no clifford.
Con errores por compuerta de orden 1E-3
, estimamos una fidelidad final de tal cálculo de aproximadamente 1E-6
, lo que implica resultados totalmente sin sentido.
Computación cuántica tolerante a fallas¶
Los errores son una ocurrencia natural en cualquier computadora. En las computadoras cuánticas, estos errores suelen ser más complejos y ocurren cuando los estados cuánticos no se preparan exactamente como deberían. Por ejemplo, sobrepasar sus valores objetivo o alejarse. Además, las perturbaciones que generan estos problemas suelen ser inevitables.
Hay varias formas de manejar estos errores. La terminología puede resultar confusa, ya que existe desacuerdo incluso dentro del campo. Lo dividiremos en tres partes principales:
Supresión
Mitigación
Corrección
Comencemos con la corrección de errores, ya que fue la primera en ser descubierta formalmente dentro del campo.
Corrección de errores¶
La corrección de errores en las computadoras clásicas es el procedimiento estándar de codificación de información de manera redundante para hacerla resistente al ruido no deseado, lo que nos permite detectar y corregir errores a medida que ocurren.
Se sabe desde hace mucho tiempo que el acoplamiento de los sistemas cuánticos a su entorno marca un límite para cualquier computación cuántica, tanto en tiempo como en tamaño. No obstante, los descubrimientos teóricos en forma de Corrección de errores cuánticos resolvieron este problema desde el principio.
TEOREMA DEL UMBRAL
Si los errores en las computadoras cuánticas pueden reducirse por debajo de cierto nivel (finito), un cálculo cuántico tolerante a fallas podría llevarse a cabo durante un tiempo arbitrario incluso en hardware ruidoso.
Referencia: M.A. Nielsen, and I.L. Chuang, Quantum Computation and Quantum Information.
Así es como esperamos lograr el objetivo final de la computación cuántica tolerante a fallas. Sin embargo, incluso si construimos hardware que pueda alcanzar el umbral prescrito, la sobrecarga para realizar la corrección de errores completa, como el recuento de qubits necesario, lo hace inviable a corto plazo; como intentaremos codificar valores lógicos de un solo qubit en múltiples qubits físicos:
\[n/d = 100/100 \quad\]
|
\[p = \text{1E-3} \quad\]
|
\[p = \text{1E-4} \quad\]
|
\[p = \text{1E-5} \quad\]
|
---|---|---|---|
Runtime [\(s\)] |
2.3 |
1.2 |
0.8 |
Qubits físicos |
140k |
40k |
16k |
Distancia |
21 |
11 |
7 |
Estos recursos de código de superficie* están mucho más allá de nuestros planes para 2025, aunque estamos trabajando arduamente en esta área para que sea factible lo antes posible.
* Los datos de la tabla anterior se basan en simulaciones para códigos de superficie con ciertas condiciones. La distancia del código se eligió para que ninguna de las compuertas T, o 100 qubits lógicos al final del tiempo de ejecución, tuviera un error mayor a \(1\text{E}-2\). El número de compuertas T es \(n \times d\) y cada ciclo de verificación de paridad toma \(1 \mu s\).
Referencia: Daniel Litinski, A Game of Surface Codes: Large-Scale Quantum Computing with Lattice Surgery, arXiv:1808.02892
Supresión de errores¶
La supresión de errores es el nivel más básico de manejo de errores. A menudo se refiere a un conjunto de técnicas realizadas cerca del hardware, como la alteración de las señales de control (es decir, a nivel de Qiskit Pulse). Para hacerlo más simple, definimos estas técnicas como la introducción de sobrecarga clásica, generalmente dentro del proceso de transpilación/compilación.
Estas técnicas son muy antiguas y se desarrollaron por primera vez fuera del campo al mismo tiempo que algunos de los primeros sistemas cuánticos controlables, como los dispositivos de imágenes por resonancia magnética.
Desacoplamiento dinámico (Dynamical Decoupling, DD)¶
Las computadoras cuánticas han adoptado algunas de estas técnicas como ecos de espín (una secuencia de pulsos que pueden ayudar a reenfocar el estado de un qubit). De hecho, los ecos de espín juegan un papel importante en una clase de técnicas conocidas como Desacoplamiento dinámico (DD), que envía pulsos a qubits inactivos para restablecer su valor a sus estados originales, deshaciendo los efectos potencialmente dañinos de qubits cercanos que se están utilizando para el cálculo.
Referencia: Lorenza Viola, and Seth Lloyd , Dynamical suppression of decoherence in two-state quantum systems, arXiv:quant-ph/9803057
[6]:
options = Options()
options.execution.shots = 1000
options.optimization_level = 3 # Dynamical decoupling
options.resilience_level = 0 # No error mitigation
with Session(service=service, backend=backend) as session:
estimator = Estimator(session=session, options=options)
job_dd = estimator.run(circuits=trotter_circuit_list, observables=obs_list)
print("job id:", job_dd.job_id)
print(job_dd.result())
expvals_unmit_dd = job_dd.result().values
expvals_unmit_dd_variance = [
metadata["variance"] / metadata["shots"] for metadata in job_dd.result().metadata
]
std_error_dd = np.sqrt(expvals_unmit_dd_variance)
job id: cdkrpk5f14jb6brgbmt0
EstimatorResult(values=array([0.87 , 0.752, 0.598, 0.484, 0.396]), metadata=[{'variance': 0.24309999999999998, 'shots': 1000}, {'variance': 0.434496, 'shots': 1000}, {'variance': 0.642396, 'shots': 1000}, {'variance': 0.765744, 'shots': 1000}, {'variance': 0.8431839999999999, 'shots': 1000}])
[7]:
plt.title("Trotter circuits expectation value")
plt.errorbar(
range(1, num_steps),
expvals_ideal,
std_error_ideal,
fmt="o",
linestyle="--",
capsize=4,
c="red",
label="Ideal",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit,
std_error_unmit,
fmt="o",
linestyle="-",
capsize=4,
c="green",
label="No mitigation",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit_dd,
std_error_dd,
fmt="o",
linestyle="-",
capsize=4,
c="blue",
label="Dynamical decoupling",
)
plt.ylabel(f"$\langle ZZZZ \\rangle$")
plt.xlabel("No. Trotter Steps")
plt.xticks([1, 2, 3, 4, 5])
plt.legend()
plt.show()

Mitigación de errores¶
La mitigación de errores introduce sobrecarga cuántica en nuestros cálculos.
Por lo general, la corrección de errores utiliza las salidas de múltiples conjuntos de cálculos ruidosos para reducir o eliminar el ruido al estimar cantidades como valores esperados, comúnmente mediante el uso de posprocesamiento clásico. En este sentido, la mitigación de errores es diferente de la corrección de errores. En lugar de corregir los errores en cada ejecución del circuito, se permite que ocurran errores, luego se infieren mejores resultados de varios de estos cálculos ruidosos.
Dado que no hay un umbral que uno deba superar antes de que la mitigación de errores cuántica sea práctica, vemos la mitigación de errores como la clave para realizar computadoras cuánticas útiles a corto plazo.
Estamos desarrollando una cartera de diferentes técnicas de mitigación de errores, buscando tres cosas principales:
Poca sobrecarga (rapidez)
Precisión mejorada (calidad)
Pocas suposiciones (escala)
Cada método viene con su propia sobrecarga asociada: una compensación entre la cantidad de cálculos cuánticos necesarios (tiempo) y la precisión de nuestros resultados. El nivel de precisión que se puede lograr también es específico de cada método y, por lo general, es inversamente proporcional a la sobrecarga mencionada anteriormente. Definiendo \(\lambda\) como el ruido base en nuestro cálculo:
Métodos |
T-REx |
ZNE |
PEC |
---|---|---|---|
Suposiciones |
Ninguna |
Capacidad para escalar el ruido |
Pleno conocimiento del ruido |
Sobrecarga de qubit |
\(1\) |
\(1\) |
\(1\) |
Sobrecarga de muestreo |
\(2\) |
\(N_\text{noise-factors}\) |
\(\mathcal{O}(e^{\lambda N_\text{layers}})\) |
Sesgo |
\(0\) |
\(\mathcal{O}(\lambda^{N_\text{noise-factors}})\) |
\(0\) |
Información más detallada está disponible en:
T-REx: arXiv:2012.09738
ZNE: arXiv:1612.02058
PEC: arXiv:1612.02058
Al tener una cartera de métodos, los usuarios pueden elegir qué técnica tiene más sentido para su problema de interés, en función de las demandas de precisión y la cantidad de sobrecarga que están dispuestos a aceptar. Estamos entusiasmados con esto porque, en los mejores escenarios, podemos lograr resultados sin sesgo (es decir, sin ruido); y queremos que esta capacidad sea accesible en toda la pila: desde el kernel hasta los algoritmos y desarrolladores de modelos.
¿Por qué es importante la mitigación de errores?¶
Necesitamos mejoras en escala, calidad y rapidez.
La promesa de la mitigación de errores es traducir el progreso continuo del hardware cuántico en mejoras continuas en los cálculos cuánticos y el procesamiento de la información cuántica. Esperamos que, si bien es insuficiente para superar por completo las imperfecciones, cada avance debe ampliar gradualmente la frontera de lo que se puede lograr en la práctica; a diferencia de un escenario en el que se hace poco o ningún progreso hasta que de repente superamos el umbral tolerante a fallas.
Más allá del circuito 100x100, visualizamos un futuro en el que la corrección y la mitigación de errores pueden funcionar de manera híbrida. En ese sentido, este enfoque ha demostrado ser efectivo en la práctica e intelectualmente desafiante.
Conceptos¶
Los siguientes términos se utilizan en esta sección.
TERMINOLOGÍA
Al igual que con todos los campos emergentes, la terminología a veces es inconsistente: las personas usan los mismos términos para referirse a cosas (ligeramente) diferentes.
Estimadores (Estimators): Estrategias para aproximar ciertos valores físicos que son fundamentalmente desconocidos.
Muestreo (Sampling): El proceso de tomar varias medidas de una o varias cosas.
Sobrecarga (Overhead): Costos adicionales introducidos por nuevas técnicas, en relación con una implementación base.
Sesgo (Bias): Una desviación sistemática en las cantidades medidas, generalmente causada por errores.
Ruido de iteración/muestra (Shot/sample noise): Incertidumbre en los resultados obtenidos debido a la falta de precisión infinita (es decir, un número finito de muestras).
Implicaciones¶
Al implementar cualquier técnica de mitigación de errores, esperamos que el sesgo en nuestros resultados se reduzca con respecto al sesgo anterior, no mitigado; en algunos casos incluso desapareciendo. Sin embargo, esto tiene un costo. A medida que reducimos el sesgo en nuestras cantidades estimadas, la variabilidad estadística aumentará (es decir, la varianza), lo que podemos explicar aumentando aún más el número de iteraciones por circuito en nuestro proceso de muestreo. Esto introducirá una sobrecarga más allá de la necesaria para reducir el sesgo, por lo que no se realiza de forma predeterminada. El usuario puede optar fácilmente por este comportamiento ajustando la cantidad de shots
por circuito en run_options
.
En términos matemáticos, esperamos que nuestro estimador de error mitigado sea tal que:
Extinción de error de lectura torcida (twirled)¶
La extinción de error de lectura torcida (Twirled readout error extinction, T-REx) utiliza una técnica conocida como giro de Pauli (Pauli twirling) para reducir el ruido introducido durante el proceso de medición cuántica. Esta técnica no asume una forma específica de ruido, lo que la hace muy general y efectiva.
Flujo de trabajo general¶
Adquirir datos para el estado cero con cambios de bits aleatorios (Pauli X antes de la medición)
Adquirir datos para el estado deseado (ruidoso) con cambios de bits aleatorios (Pauli X antes de la medición)
Calcular la función especial para cada conjunto de datos y dividir.
Referencia: E. van den Berg, Z. Minev, and K. Temme, Model-free readout-error mitigation for quantum expectation values arXiv:2012.09738
[8]:
options = Options()
options.resilience_level = 1 # T-REx
options.optimization_level = 0 # No optimization
options.execution.shots = 1000
with Session(service=service, backend=backend) as session:
estimator = Estimator(session=session, options=options)
job_trex = estimator.run(circuits=trotter_circuit_list, observables=obs_list)
print("job id:", job_trex.job_id)
print(job_trex.result())
expvals_unmit_trex = job_trex.result().values
expvals_unmit_trex_variance = [
metadata["variance"] / metadata["shots"] for metadata in job_trex.result().metadata
]
std_error_trex = np.sqrt(expvals_unmit_trex_variance)
job id: cdkrpq7tlcfkm5f0demg
EstimatorResult(values=array([0.95941791, 0.81652588, 0.68894371, 0.55625825, 0.45674416]), metadata=[{'variance': 0.733385959939609, 'shots': 1008, 'readout_mitigation_num_twirled_circuits': 16, 'readout_mitigation_shots_calibration': 8192}, {'variance': 0.9871541699414397, 'shots': 1008, 'readout_mitigation_num_twirled_circuits': 16, 'readout_mitigation_shots_calibration': 8192}, {'variance': 1.1792252443219302, 'shots': 1008, 'readout_mitigation_num_twirled_circuits': 16, 'readout_mitigation_shots_calibration': 8192}, {'variance': 1.3444454335924159, 'shots': 1008, 'readout_mitigation_num_twirled_circuits': 16, 'readout_mitigation_shots_calibration': 8192}, {'variance': 1.4452534486647257, 'shots': 1008, 'readout_mitigation_num_twirled_circuits': 16, 'readout_mitigation_shots_calibration': 8192}])
[9]:
plt.title("Trotter circuits expectation value")
plt.errorbar(
range(1, num_steps),
expvals_ideal,
std_error_ideal,
fmt="o",
linestyle="--",
capsize=4,
c="red",
label="Ideal",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit,
std_error_unmit,
fmt="o",
linestyle="-",
capsize=4,
c="green",
label="No mitigation",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit_trex,
std_error_trex,
fmt="o",
linestyle="-",
capsize=4,
c="violet",
label="T-REx",
)
plt.ylabel(f"$\langle ZZZZ \\rangle$")
plt.xlabel("No. Trotter Steps")
plt.xticks([1, 2, 3, 4, 5])
plt.legend()
plt.show()

Extrapolación de ruido cero¶
La extrapolación de ruido cero (zero noise extrapolation, ZNE) funciona amplificando primero el ruido en el circuito que está preparando el estado cuántico deseado, obteniendo medidas para varios niveles diferentes de ruido y usando esas medidas para inferir el resultado sin ruido.
Flujo de trabajo general¶
Amplificar el ruido del circuito para varios factores de ruido
Ejecutar cada circuito amplificado de ruido
Extrapolar de regreso al límite de ruido cero
[10]:
options = Options()
options.execution.shots = 1000
options.optimization_level = 0 # No optimization
options.resilience_level = 2 # ZNE
with Session(service=service, backend=backend) as session:
estimator = Estimator(session=session, options=options)
job_zne = estimator.run(circuits=trotter_circuit_list, observables=obs_list)
print("job id:", job_zne.job_id)
print(job_zne.result())
expvals_unmit_zne = job_zne.result().values
# Standard error: coming soon!
job id: cdkrq4i2h6kvivdb2an0
EstimatorResult(values=array([0.896 , 0.86833333, 0.82716667, 0.63116667, 0.58366667]), metadata=[{'zne': {'noise_amplification': {'noise_amplifier': "<TwoQubitAmplifier:{'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 3, 5], 'values': [0.84, 0.788, 0.664], 'variance': [0.2944000000000001, 0.37905599999999995, 0.5591039999999999], 'shots': [1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'LinearExtrapolator'}}}, {'zne': {'noise_amplification': {'noise_amplifier': "<TwoQubitAmplifier:{'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 3, 5], 'values': [0.778, 0.614, 0.43], 'variance': [0.39471599999999996, 0.623004, 0.8151], 'shots': [1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'LinearExtrapolator'}}}, {'zne': {'noise_amplification': {'noise_amplifier': "<TwoQubitAmplifier:{'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 3, 5], 'values': [0.718, 0.498, 0.28], 'variance': [0.484476, 0.751996, 0.9216], 'shots': [1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'LinearExtrapolator'}}}, {'zne': {'noise_amplification': {'noise_amplifier': "<TwoQubitAmplifier:{'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 3, 5], 'values': [0.54, 0.376, 0.19], 'variance': [0.7083999999999999, 0.858624, 0.9639], 'shots': [1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'LinearExtrapolator'}}}, {'zne': {'noise_amplification': {'noise_amplifier': "<TwoQubitAmplifier:{'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 3, 5], 'values': [0.498, 0.31, 0.142], 'variance': [0.751996, 0.9039, 0.979836], 'shots': [1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'LinearExtrapolator'}}}])
[11]:
plt.title("Trotter circuits expectation value")
plt.errorbar(
range(1, num_steps),
expvals_ideal,
std_error_ideal,
fmt="o",
linestyle="--",
capsize=4,
c="red",
label="Ideal",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit,
std_error_unmit,
fmt="o",
linestyle="-",
capsize=4,
c="green",
label="No mitigation",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit_zne,
[0] * (num_steps - 1),
fmt="o",
linestyle="-",
capsize=4,
c="cyan",
label="ZNE",
)
plt.xlabel("No. Trotter Steps")
plt.ylabel(f"$\langle ZZZZ \\rangle$")
plt.xticks([1, 2, 3, 4, 5])
plt.legend()
plt.show()

Cancelación probabilística de errores¶
Muestras de cancelación probabilística de errores (probabilistic error cancellation, PEC) para una colección de circuitos que, en promedio, imita un canal inversor de ruido para cancelar el ruido en el cálculo deseado. Este proceso es un poco como funcionan los auriculares con cancelación de ruido y produce excelentes resultados; sin embargo, no es tan general como otros métodos, y la sobrecarga de muestreo es exponencial.
Referencia: E. van den Berg, Z. Minev, A. Kandala, and K. Temme, Probabilistic error cancellation with sparse Pauli-Lindblad models on noisy quantum processors arXiv:2201.09866
Flujo de trabajo general¶
Paso 1: Giros de Pauli (Pauli twirling)¶
Paso 2: Repetir la capa y aprender el ruido¶
Paso 3: Obtener una fidelidad (error para cada canal de ruido)¶
[ ]:
def interim_results_callback(job_id, result):
now = datetime.datetime.now()
print(now, "*** Callback ***", result, "\n")
options = Options()
options.optimization_level = 0 # No optimization
options.execution.shots = 100
options.resilience_level = 3 # PEC
options.environment.callback = interim_results_callback
with Session(service=service, backend=backend) as session:
estimator_pec = Estimator(session=session, options=options)
job_pec = estimator_pec.run(circuits=trotter_circuit_list, observables=obs_list)
print("job id:", job_pec.job_id)
expvals_pec = job_pec.result().values
std_error_pec = [metadata["standard_error"] for metadata in job_pec.result().metadata]
job id: cdkqv522h6kvivdat0vg
2022-11-07 20:23:43.013816 *** Callback *** {'unique_layers_detected': 2, 'total_layers': 60}
2022-11-07 20:30:41.251325 *** Callback *** {'msg': 'Sampling overhead for layer 1/2: 1.0263820029324646'}
2022-11-07 20:37:38.920151 *** Callback *** {'msg': 'Sampling overhead for layer 2/2: 1.0692954781746'}
2022-11-07 20:37:39.334815 *** Callback *** {'sampling_overhead_by_layer': [1.0692954781746, 1.0263820029324646], 'unique_layers': 2, 'total_sampling_overhead': 1.4508651011392564}
2022-11-07 20:37:39.336883 *** Callback *** {'sampling_overhead_by_layer': [1.0692954781746, 1.0263820029324646], 'unique_layers': 2, 'total_sampling_overhead': 1.2045186180127132}
2022-11-07 20:37:39.336983 *** Callback *** {'sampling_overhead_by_layer': [1.0692954781746, 1.0263820029324646], 'unique_layers': 2, 'total_sampling_overhead': 1.7475940265471324}
2022-11-07 20:37:39.337099 *** Callback *** {'sampling_overhead_by_layer': [1.0692954781746, 1.0263820029324646], 'unique_layers': 2, 'total_sampling_overhead': 2.105009541703825}
2022-11-07 20:37:39.338120 *** Callback *** {'sampling_overhead_by_layer': [1.0692954781746, 1.0263820029324646], 'unique_layers': 2, 'total_sampling_overhead': 2.5355231840766654}
2022-11-07 20:44:17.157534 *** Callback *** {'values': array([0.96681631, 0.96346463, 0.81458917, 0.83279075, 0.71165489]), 'metadata': [{'standard_error': 0.04741526161355738, 'confidence_interval': [0.6946850904749993, 1.2389475260753755], 'confidence_level': 0.95, 'shots': 15360, 'samples': 120, 'sampling_overhead': 1.2045186180127132, 'total_mitigated_layers': 4}, {'standard_error': 0.06003453067758544, 'confidence_interval': [0.6917633123010369, 1.235165948939192], 'confidence_level': 0.95, 'shots': 18560, 'samples': 145, 'sampling_overhead': 1.4508651011392564, 'total_mitigated_layers': 8}, {'standard_error': 0.07893102265063534, 'confidence_interval': [0.5423767896024972, 1.086801560321982], 'confidence_level': 0.95, 'shots': 22272, 'samples': 174, 'sampling_overhead': 1.7475940265471324, 'total_mitigated_layers': 12}, {'standard_error': 0.08198342212333354, 'confidence_interval': [0.5608466609152284, 1.104734830411759], 'confidence_level': 0.95, 'shots': 26880, 'samples': 210, 'sampling_overhead': 2.105009541703825, 'total_mitigated_layers': 16}, {'standard_error': 0.08955468433998504, 'confidence_interval': [0.43973826826406204, 0.9835715192472465], 'confidence_level': 0.95, 'shots': 32384, 'samples': 253, 'sampling_overhead': 2.5355231840766654, 'total_mitigated_layers': 20}]}
[ ]:
plt.title("Trotter circuits expectation value")
plt.errorbar(
range(1, num_steps),
expvals_ideal,
std_error_ideal,
fmt="o",
linestyle="--",
capsize=4,
c="red",
label="Ideal",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit,
std_error_unmit,
fmt="o",
linestyle="-",
capsize=4,
c="green",
label="No mitigation",
)
plt.errorbar(
range(1, num_steps),
expvals_pec,
std_error_pec,
fmt="d",
linestyle="-",
capsize=4,
c="orange",
label="PEC",
)
plt.ylabel(f"$\langle ZZZZ \\rangle$")
plt.xlabel("No. Trotter Steps")
plt.xticks([1, 2, 3, 4, 5])
plt.legend()
plt.show()

Explicación de los mensajes de devolución de llamada de PEC¶
Capas detectadas:
2022-11-07 20:23:43.013816 *** Callback *** {'unique_layers_detected': 2, 'total_layers': 60}
En la lista de circuitos pasados al Estimator, se detectaron un total de 60 capas y dos de ellas fueron únicas. Qiskit Runtime aprenderá el modelo de ruido para las dos capas únicas.
Sobrecarga de muestreo para capas:
2022-11-07 20:30:41.251325 *** Callback *** {'msg': 'Sampling overhead for layer 1/2: 1.0263820029324646'}
2022-11-07 20:37:38.920151 *** Callback *** {'msg': 'Sampling overhead for layer 2/2: 1.0692954781746'}
Estos mensajes muestran la sobrecarga de muestreo para cada una de las capas únicas. Ten en cuenta que tomó aproximadamente 7 minutos aprender el modelo de ruido de cada capa.
Explicación de los mensajes de devolución de llamada de PEC¶
Capas detectadas:
2022-11-07 20:23:43.013816 *** Callback *** {'unique_layers_detected': '2, total_layers: 60'}
En la lista de circuitos pasados a Estimator, se detectaron un total de 60 capas y dos de ellas fueron únicas. Qiskit Runtime aprenderá el modelo de ruido para las dos capas únicas.
Sobrecarga de muestreo para capas:
2022-11-07 20:30:41.251325 *** Callback *** {'msg': 'Sampling overhead for layer 1/2: 1.0263820029324646'}
2022-11-07 20:37:38.920151 *** Callback *** {'msg': 'Sampling overhead for layer 2/2: 1.0692954781746'}
Estos mensajes muestran la sobrecarga de muestreo para cada una de las capas únicas. Ten en cuenta que tomó aproximadamente 7 minutos aprender el modelo de ruido de cada capa.
Sobrecarga de muestreo total del circuito
Sobrecarga de muestreo total del circuito 1:
1.2045186180127132
2022-11-07 20:37:39.336883 *** Callback *** {sampling_overhead_by_layer: [1.0692954781746, 1.0263820029324646], unique_layers: 2, total_sampling_overhead: 1.2045186180127132}
Sobrecarga de muestreo total del circuito 2:
1.4508651011392564
2022-11-07 20:37:39.334815 *** Callback *** {sampling_overhead_by_layer: [1.0692954781746, 1.0263820029324646], unique_layers: 2, total_sampling_overhead: 1.4508651011392564}
Sobrecarga de muestreo total del circuito 3:
1.7475940265471324
2022-11-07 20:37:39.336983 *** Callback *** {sampling_overhead_by_layer: [1.0692954781746, 1.0263820029324646], unique_layers: 2, total_sampling_overhead: 1.7475940265471324}
Sobrecarga de muestreo total del circuito 4:
2.105009541703825
2022-11-07 20:37:39.337099 *** Callback *** {sampling_overhead_by_layer: [1.0692954781746, 1.0263820029324646], unique_layers: 2, total_sampling_overhead: 2.105009541703825}
Sobrecarga de muestreo total del circuito 5:
2.5355231840766654
2022-11-07 20:37:39.338120 *** Callback *** {sampling_overhead_by_layer: [1.0692954781746, 1.0263820029324646], unique_layers: 2, total_sampling_overhead: 2.5355231840766654}
La sobrecarga de muestreo aumenta cuando hay más capas a mitigar.
[ ]:
print(job_pec.result())
EstimatorResult(values=array([0.96681631, 0.96346463, 0.81458917, 0.83279075, 0.71165489]), metadata=[{'standard_error': 0.04741526161355738, 'confidence_interval': [0.6946850904749993, 1.2389475260753755], 'confidence_level': 0.95, 'shots': 15360, 'samples': 120, 'sampling_overhead': 1.2045186180127132, 'total_mitigated_layers': 4}, {'standard_error': 0.06003453067758544, 'confidence_interval': [0.6917633123010369, 1.235165948939192], 'confidence_level': 0.95, 'shots': 18560, 'samples': 145, 'sampling_overhead': 1.4508651011392564, 'total_mitigated_layers': 8}, {'standard_error': 0.07893102265063534, 'confidence_interval': [0.5423767896024972, 1.086801560321982], 'confidence_level': 0.95, 'shots': 22272, 'samples': 174, 'sampling_overhead': 1.7475940265471324, 'total_mitigated_layers': 12}, {'standard_error': 0.08198342212333354, 'confidence_interval': [0.5608466609152284, 1.104734830411759], 'confidence_level': 0.95, 'shots': 26880, 'samples': 210, 'sampling_overhead': 2.105009541703825, 'total_mitigated_layers': 16}, {'standard_error': 0.08955468433998504, 'confidence_interval': [0.43973826826406204, 0.9835715192472465], 'confidence_level': 0.95, 'shots': 32384, 'samples': 253, 'sampling_overhead': 2.5355231840766654, 'total_mitigated_layers': 20}])
Metadatos de PEC¶
Circuito 1:
{
"standard_error": 0.04741526161355738,
"confidence_interval": [
0.6946850904749993,
1.2389475260753755
],
"confidence_level": 0.95,
"shots": 15360,
"samples": 120,
"sampling_overhead": 1.2045186180127132,
"total_mitigated_layers": 4
}
Circuito 2:
{
"standard_error": 0.06003453067758544,
"confidence_interval": [
0.6917633123010369,
1.235165948939192
],
"confidence_level": 0.95,
"shots": 18560,
"samples": 145,
"sampling_overhead": 1.4508651011392564,
"total_mitigated_layers": 8
}
Circuito 3:
{
"standard_error": 0.07893102265063534,
"confidence_interval": [
0.5423767896024972,
1.086801560321982
],
"confidence_level": 0.95,
"shots": 22272,
"samples": 174,
"sampling_overhead": 1.7475940265471324,
"total_mitigated_layers": 12
}
Circuito 4:
{
"standard_error": 0.08198342212333354,
"confidence_interval": [
0.5608466609152284,
1.104734830411759
],
"confidence_level": 0.95,
"shots": 26880,
"samples": 210,
"sampling_overhead": 2.105009541703825,
"total_mitigated_layers": 16
}
Circuito 5
{
"standard_error": 0.08955468433998504,
"confidence_interval": [
0.43973826826406204,
0.9835715192472465
],
"confidence_level": 0.95,
"shots": 32384,
"samples": 253,
"sampling_overhead": 2.5355231840766654,
"total_mitigated_layers": 20
}
[ ]:
pec_metadata = job_pec.result().metadata
fig, ax = plt.subplots()
fig.subplots_adjust(right=0.75)
twin1 = ax.twinx()
twin2 = ax.twinx()
twin3 = ax.twinx()
twin2.spines.right.set_position(("axes", 1.2))
twin3.spines.right.set_position(("axes", 1.4))
(p1,) = ax.plot(
range(1, num_steps),
[m["total_mitigated_layers"] for m in pec_metadata],
"b-",
label="Total mitigated layers",
)
(p2,) = twin1.plot(
range(1, num_steps),
[m["sampling_overhead"] for m in pec_metadata],
"r-",
label="Sampling overhead",
)
(p3,) = twin2.plot(range(1, num_steps), [m["samples"] for m in pec_metadata], "g-", label="Samples")
(p4,) = twin3.plot(range(1, num_steps), [m["shots"] for m in pec_metadata], "c-", label="Shots")
ax.set_ylim(0, 20)
twin1.set_ylim(0, 2.8)
twin2.set_ylim(0, 300)
twin3.set_ylim(0, 35000)
ax.set_xlabel("No. Trotter Steps")
ax.set_ylabel("Total mitigated layers")
twin1.set_ylabel("Sampling overhead")
twin2.set_ylabel("Samples")
twin3.set_ylabel("Shots")
ax.yaxis.label.set_color(p1.get_color())
twin1.yaxis.label.set_color(p2.get_color())
twin2.yaxis.label.set_color(p3.get_color())
twin3.yaxis.label.set_color(p4.get_color())
tkw = dict(size=4, width=1.5)
ax.tick_params(axis="y", colors=p1.get_color(), **tkw)
twin1.tick_params(axis="y", colors=p2.get_color(), **tkw)
twin2.tick_params(axis="y", colors=p3.get_color(), **tkw)
twin3.tick_params(axis="y", colors=p4.get_color(), **tkw)
plt.xticks([1, 2, 3, 4, 5])
ax.legend(handles=[p1, p2, p3, p4])
plt.title("PEC metadata")
plt.show()

Gráfica combinada¶
[ ]:
from matplotlib.pyplot import figure
plt.errorbar(
range(1, num_steps),
expvals_ideal,
std_error_ideal,
fmt="o",
linestyle="--",
capsize=4,
c="red",
label="Ideal",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit,
std_error_unmit,
fmt="o",
linestyle="-",
capsize=4,
c="green",
label="No mitigation",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit_trex,
std_error_trex,
fmt="o",
linestyle="-",
capsize=4,
c="violet",
label="T-REx",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit_zne,
[0] * (num_steps - 1),
fmt="o",
linestyle="-",
capsize=4,
c="cyan",
label="ZNE",
)
plt.errorbar(
range(1, num_steps),
expvals_pec,
std_error_pec,
fmt="d",
linestyle="-",
capsize=4,
c="orange",
label="PEC",
)
plt.title("Trotter circuits expectation value")
plt.ylabel(f"$\langle ZZZZ \\rangle$")
plt.xlabel("No. Trotter Steps")
plt.xticks([1, 2, 3, 4, 5])
plt.legend()
plt.show()

Opciones avanzadas de ZNE¶
Amplificación de ruido¶
Como primera aproximación, proporcionamos una técnica de amplificación de ruido conocida como plegamiento unitario (unitary folding).
Referencia: Tudor Giurgica-Tiron, Yousef Hindy, Ryan LaRose, Andrea Mari, and William J. Zeng, Digital zero noise extrapolation for quantum error mitigation arXiv:2005.10921.
Digital vs analógico¶
Local vs global¶
Extrapolación¶
Perfiles de ruido útiles¶
Perfiles de ruido inútiles¶
[ ]:
options = Options()
options.execution.shots = 1000
options.optimization_level = 0 # no optimization
options.resilience_level = 2 # ZNE
options.resilience.noise_factors = [1, 2, 3, 4]
options.resilience.noise_amplifier = "LocalFoldingAmplifier"
options.resilience.extrapolator = "QuadraticExtrapolator"
with Session(service=service, backend="ibmq_montreal") as session:
estimator = Estimator(session=session, options=options)
job_zne_options = estimator.run(circuits=trotter_circuit_list, observables=obs_list)
print("job id:", job_zne_options.job_id)
print(job_zne_options.result())
job id: cdkrqbdf14jb6brgbrl0
EstimatorResult(values=array([0.9285, 0.8165, 0.835 , 0.6815, 0.4945]), metadata=[{'zne': {'noise_amplification': {'noise_amplifier': "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 2, 3, 4], 'values': [0.838, 0.798, 0.738, 0.752], 'variance': [0.297756, 0.36319599999999996, 0.455356, 0.434496], 'shots': [1000, 1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'QuadraticExtrapolator'}}}, {'zne': {'noise_amplification': {'noise_amplifier': "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 2, 3, 4], 'values': [0.732, 0.676, 0.572, 0.522], 'variance': [0.46417600000000003, 0.543024, 0.6728160000000001, 0.727516], 'shots': [1000, 1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'QuadraticExtrapolator'}}}, {'zne': {'noise_amplification': {'noise_amplifier': "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 2, 3, 4], 'values': [0.674, 0.51, 0.436, 0.328], 'variance': [0.5457239999999999, 0.7399, 0.809904, 0.892416], 'shots': [1000, 1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'QuadraticExtrapolator'}}}, {'zne': {'noise_amplification': {'noise_amplifier': "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 2, 3, 4], 'values': [0.512, 0.372, 0.266, 0.188], 'variance': [0.7378560000000001, 0.8616159999999999, 0.929244, 0.964656], 'shots': [1000, 1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'QuadraticExtrapolator'}}}, {'zne': {'noise_amplification': {'noise_amplifier': "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 2, 3, 4], 'values': [0.442, 0.35, 0.268, 0.13], 'variance': [0.804636, 0.8775000000000001, 0.928176, 0.9831], 'shots': [1000, 1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'QuadraticExtrapolator'}}}])
{
"values": [
0.928499999999999,
0.8165,
0.835,
0.6815000000000001,
0.49449999999999983
],
"metadata": [
{
"zne": {
"noise_amplification": {
"noise_amplifier": "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>",
"noise_factors": [
1,
2,
3,
4
],
"values": [
0.838,
0.798,
0.738,
0.752
],
"variance": [
0.297756,
0.36319599999999996,
0.455356,
0.434496
],
"shots": [
1000,
1000,
1000,
1000
]
},
"extrapolation": {
"extrapolator": "QuadraticExtrapolator"
}
}
},
{
"zne": {
"noise_amplification": {
"noise_amplifier": "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>",
"noise_factors": [
1,
2,
3,
4
],
"values": [
0.732,
0.676,
0.572,
0.522
],
"variance": [
0.46417600000000003,
0.543024,
0.6728160000000001,
0.727516
],
"shots": [
1000,
1000,
1000,
1000
]
},
"extrapolation": {
"extrapolator": "QuadraticExtrapolator"
}
}
},
{
"zne": {
"noise_amplification": {
"noise_amplifier": "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>",
"noise_factors": [
1,
2,
3,
4
],
"values": [
0.674,
0.51,
0.436,
0.328
],
"variance": [
0.5457239999999999,
0.7399,
0.809904,
0.892416
],
"shots": [
1000,
1000,
1000,
1000
]
},
"extrapolation": {
"extrapolator": "QuadraticExtrapolator"
}
}
},
{
"zne": {
"noise_amplification": {
"noise_amplifier": "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>",
"noise_factors": [
1,
2,
3,
4
],
"values": [
0.512,
0.372,
0.266,
0.188
],
"variance": [
0.7378560000000001,
0.8616159999999999,
0.929244,
0.964656
],
"shots": [
1000,
1000,
1000,
1000
]
},
"extrapolation": {
"extrapolator": "QuadraticExtrapolator"
}
}
},
{
"zne": {
"noise_amplification": {
"noise_amplifier": "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>",
"noise_factors": [
1,
2,
3,
4
],
"values": [
0.442,
0.35,
0.268,
0.13
],
"variance": [
0.804636,
0.8775000000000001,
0.928176,
0.9831
],
"shots": [
1000,
1000,
1000,
1000
]
},
"extrapolation": {
"extrapolator": "QuadraticExtrapolator"
}
}
}
]
}
[1]:
import qiskit_ibm_runtime
qiskit_ibm_runtime.version.get_version_info()
[1]:
'0.11.1'
[ ]:
from qiskit.tools import jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Qiskit Software | Version |
---|---|
qiskit-terra | 0.22.2 |
qiskit-aer | 0.11.0 |
qiskit-ibmq-provider | 0.19.2 |
System information | |
Python version | 3.10.4 |
Python compiler | Clang 12.0.0 |
Python build | main, Mar 31 2022 03:38:35 |
OS | Darwin |
CPUs | 4 |
Memory (Gb) | 16.0 |
Tue Nov 08 12:15:46 2022 EST |
This code is a part of Qiskit
© Copyright IBM 2017, 2022.
This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.