Spanish
Idiomas
English
Japanese
Spanish

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.

d73e54dbce9f4a8086b5e6b277a7fe18

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:

  1. Supresión

  2. Mitigación

  3. 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()
../_images/tutorials_Error-Suppression-and-Error-Mitigation_18_0.png

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:

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.

5249df255be44acb863900b608d2304b

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:

\[\begin{split}0 \leq | \text{Bias}[{\langle}O{\rangle}_\text{em}] | \leq | \text{Bias}[{\langle}O{\rangle}_\text{noisy}] | \\ | \text{Var}[{\langle}O{\rangle}_\text{em}] | \geq | \text{Var}[{\langle}O{\rangle}_\text{noisy}] | > 0\end{split}\]

b1df3c2659bd427baf170c51b9ea0759

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

  1. Adquirir datos para el estado cero con cambios de bits aleatorios (Pauli X antes de la medición)

  2. Adquirir datos para el estado deseado (ruidoso) con cambios de bits aleatorios (Pauli X antes de la medición)

  3. Calcular la función especial para cada conjunto de datos y dividir.

c2ab3b69441d48b486c106717aba1fa6

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()
../_images/tutorials_Error-Suppression-and-Error-Mitigation_28_0.png

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

  1. Amplificar el ruido del circuito para varios factores de ruido

  2. Ejecutar cada circuito amplificado de ruido

  3. Extrapolar de regreso al límite de ruido cero

7348c8b5fb5a436eba53352f131718ec

[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()
../_images/tutorials_Error-Suppression-and-Error-Mitigation_31_0.png

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

12a3a12f58bf45f5a463a10776147b57

Paso 1: Giros de Pauli (Pauli twirling)

be3fe6d914784116bf344ff8e1eedf3c

Paso 2: Repetir la capa y aprender el ruido

f90d9e859545476182a1c8632af17ca4

Paso 3: Obtener una fidelidad (error para cada canal de ruido)

c0ab0476af4944b0ba4d5676b29f0aa4

[ ]:
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()
../_images/tutorials_Error-Suppression-and-Error-Mitigation_37_0.png

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()
../_images/tutorials_Error-Suppression-and-Error-Mitigation_43_0.png

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()
../_images/tutorials_Error-Suppression-and-Error-Mitigation_45_0.png

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

7ea607248fa042158712b9a6e26c5e80

Local vs global

0e858f15d9fa4f54889ef88fc691b786

Extrapolación

Perfiles de ruido útiles

0869632b991141ec9b6e3c8f758688a4

Perfiles de ruido inútiles

cc42c1d3f2214f80a9845d9344c775bd

[ ]:
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 SoftwareVersion
qiskit-terra0.22.2
qiskit-aer0.11.0
qiskit-ibmq-provider0.19.2
System information
Python version3.10.4
Python compilerClang 12.0.0
Python buildmain, Mar 31 2022 03:38:35
OSDarwin
CPUs4
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.