Saltar al contenido principal
Este proyecto está en fase beta. ¿Encontraste un error? Abre un issue en GitHub. ¿Tienes una pregunta o una idea? Pregunta en Discussions — ¡nos encantaría tu opinión!
¿Cómo es la calidad de la traducción en esta página?

Inicio rápido


title: Inicio rápido description: Una guía de inicio rápido para el addon de Qiskit Shaded lightcones (qiskit-addon-slc)​

Esta guía muestra un ejemplo mínimo funcional del paquete qiskit-addon-slc. Calcula un cono de luz sombreado para reducir el coste de muestreo de la cancelación probabilística de errores (PEC).

PEC mitiga el ruido de las compuertas muestreando a partir de una descomposición en cuasiprobabilidades del canal de ruido inverso. Su coste de muestreo crece con cada término de error que debe mitigar; sin embargo, no todos los errores afectan al observable por igual. Un error fuera del cono de luz causal del observable no puede influir en el valor esperado medido, e incluso dentro del cono de luz, algunos errores son más perjudiciales que otros. Un cono de luz sombreado cuantifica esto acotando el efecto que cada término de error de Pauli tiene sobre el observable. Truncar los términos de error con el menor efecto reduce el modelo de ruido que PEC tiene que mitigar, disminuyendo el coste de muestreo a cambio de un pequeño sesgo acotado.

Para ver cómo construir un flujo de trabajo realista y ejecutarlo en hardware cuántico, consulta el tutorial Cancelación probabilística de errores con conos de luz sombreados en IBM Quantum Platform.

1. Prepara las entradas para SLC​

Primero, construye un circuito de Ising de campo transversal con descomposición de Trotter de 10 qubits y elige un observable ZZ de un solo qubit sobre el qubit central.

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"numpy": "numpy", "qiskit": "qiskit", "qiskit_addon_slc": "qiskit-addon-slc", "samplomatic": "samplomatic"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Pauli

def trotter_ising_circuit(num_qubits, num_steps, rx_angle, rzz_angle):
"""Trotterized transverse-field Ising evolution on a 1D chain."""
circuit = QuantumCircuit(num_qubits)
for _ in range(num_steps):
circuit.rx(rx_angle, range(num_qubits))
circuit.barrier()
for start in (0, 1): # even then odd bonds
for i in range(start, num_qubits - 1, 2):
circuit.rzz(rzz_angle, i, i + 1)
circuit.barrier()
return circuit

num_qubits = 10
circuit = trotter_ising_circuit(
num_qubits, num_steps=4, rx_angle=np.pi / 16, rzz_angle=-np.pi / 3
)

# Measure <Z> on the middle qubit
observable = Pauli("I" * num_qubits).compose("Z", [num_qubits // 2])

print(f"Observable: {observable}")
circuit.draw("mpl", fold=-1, scale=0.7)
Observable: IIIIZIIIII

Output of the previous code cell

SLC opera sobre las capas ruidosas de compuertas de dos qubits del circuito. Aquí usamos samplomatic para agrupar las compuertas en cajas anotadas y adjuntar una anotación de inyección de ruido a cada capa de dos qubits. SLC requiere que cada caja ruidosa tenga un modifier_ref único, que proporciona inject_noise_strategy="individual_modification"; con la estrategia predeterminada de samplomatic, las cotas salen mal o su cálculo nunca termina. Después, generate_noise_model_paulis enumera los términos de error de Pauli de cada capa ruidosa única.

from qiskit_addon_slc.utils import generate_noise_model_paulis
from samplomatic.transpiler import generate_boxing_pass_manager
from samplomatic.utils import find_unique_box_instructions

# Group gates into boxes and annotate each two-qubit layer with a noise-injection point
boxing_pass = generate_boxing_pass_manager(
inject_noise_targets="all",
inject_noise_strategy="individual_modification", # required: one modifier_ref per box
inject_noise_site="after",
twirling_strategy="active",
remove_barriers="never",
)
boxed_circuit = boxing_pass.run(circuit)

# Enumerate the 1- and 2-weight Pauli error terms of each unique noisy layer
noise_model_paulis = generate_noise_model_paulis(
find_unique_box_instructions(boxed_circuit)
)

num_terms = sum(len(paulis) for paulis in noise_model_paulis.values())
print(f"Noisy layers: {len(noise_model_paulis)}")
print(f"Pauli error terms across all layers: {num_terms}")
Noisy layers: 2
Pauli error terms across all layers: 198

2. Calcula el cono de luz sombreado​

El cono de luz sombreado se construye asignando una escala a cada término de error de Pauli del modelo de ruido según cuánto efecto tiene sobre el valor esperado del observable. Estas escalas se derivan de las cotas de error hacia delante y hacia atrás de cada término (descritas a continuación), así como de su tasa de error:

  • compute_forward_bounds evoluciona cada término de error hacia delante hasta el final del circuito para acotar su efecto sobre el observable medido allí.

  • compute_backward_bounds evoluciona cada término de error hacia atrás hasta el inicio del circuito para acotar su efecto sobre el estado inicial.

merge_bounds combina ambas en una única cota por término de error. Cada cota se escala por la tasa de error del término. Estas tasas suelen provenir de un experimento de aprendizaje de ruido (como NoiseLearnerV3); esta guía usa tasas aleatorias por simplicidad.

from qiskit.quantum_info import PauliLindbladMap, QubitSparsePauliList
from qiskit_addon_slc.bounds import (
compute_backward_bounds,
compute_forward_bounds,
merge_bounds,
)

forward_bounds = compute_forward_bounds(
boxed_circuit, noise_model_paulis, observable
)
backward_bounds = compute_backward_bounds(boxed_circuit, noise_model_paulis)

# Stand-in for rates that would be measured by a noise-learning experiment on hardware
rng = np.random.default_rng(42)
noise_rates = {
layer_id: PauliLindbladMap.from_components(
rng.random(len(paulis)) * 5e-3,
QubitSparsePauliList.from_sparse_list(
paulis.to_sparse_list(), paulis.num_qubits
),
)
for layer_id, paulis in noise_model_paulis.items()
}

merged_bounds = merge_bounds(
boxed_circuit, forward_bounds, backward_bounds, noise_rates
)
Optimal spacetime partitioning not implemented!Just partitioning list of noisy boxes.

En la visualización del cono de luz sombreado de abajo, cada caja se sombrea según cuán fuertemente pueden afectar al observable los errores en ese sitio. Las cajas brillantes llevan las cotas más grandes, mientras que las cajas que se desvanecen en el fondo contienen términos de error que tienen poco efecto en el cálculo; estos errores son candidatos naturales para eliminarse del modelo de ruido. Los valores de la visualización de abajo representan sumas de las cotas de error de todos los errores de Pauli en ese sitio, por lo que algunos valores crecen más que 2.0, la cota de cualquier error de Pauli individual.

from qiskit_addon_slc.visualization import draw_shaded_lightcone

draw_shaded_lightcone(
boxed_circuit, merged_bounds, noise_model_paulis, fold=-1, scale=0.5
)

Output of the previous code cell

3. Reduce el coste de muestreo​

compute_local_scales convierte el cono de luz sombreado en una configuración concreta de PEC. Prioriza los términos de error según su efecto acotado sobre el observable y trunca los de menor impacto hasta alcanzar el bias_tolerance solicitado. Devuelve escalas para cada término de error: 0.0 para los términos que se ignoran durante la mitigación y -1.0 para los términos que deben mitigarse. La función también devuelve la sobrecarga resultante del coste de muestreo (γ2\gamma^2) y una cota del sesgo residual en que se incurre por el truncamiento.

Establecer bias_tolerance=0.0 mitiga todos los términos de error dentro del cono de luz causal del observable y da un coste de muestreo de referencia. Permitir un pequeño sesgo deja que SLC elimine los términos de bajo impacto y reduzca aún más ese coste.

from qiskit_addon_slc.bounds import compute_local_scales

_, full_cost, full_bias = compute_local_scales(
boxed_circuit, merged_bounds, noise_rates, bias_tolerance=0.0
)
local_scales, reduced_cost, reduced_bias = compute_local_scales(
boxed_circuit, merged_bounds, noise_rates, bias_tolerance=0.05
)

print(
f"Full PEC (bias_tolerance=0.0) : sampling cost {full_cost:6.3f}, residual bias {full_bias:5.3f}"
)
print(
f"Shaded (bias_tolerance=0.05): sampling cost {reduced_cost:6.3f}, residual bias {reduced_bias:5.3f}"
)
print(
f"\nSampling-cost reduction: {(1 - reduced_cost / full_cost):.0%} for <= 0.05 bias"
)
Full PEC (bias_tolerance=0.0) : sampling cost 21.206, residual bias 0.000
Shaded (bias_tolerance=0.05): sampling cost 5.403, residual bias 0.049

Sampling-cost reduction: 75% for <= 0.05 bias