Skip to main content
IBM Quantum Platform


title: "Démarrage rapide" description: "Guide de démarrage rapide pour l'extension Qiskit « Shaded lightcones » (qiskit-addon-slc)"

Démarrage rapide

Ce guide présente un exemple minimal fonctionnel du paquet qiskit-addon-slc . Nous calculons un cône de lumière ombré afin de réduire le coût d'échantillonnage de la correction probabiliste des erreurs (PEC).

Le PEC atténue le bruit de porte en effectuant un échantillonnage à partir d'une décomposition en quasi-probabilités du canal de bruit inverse. Le coût de l'échantillonnage augmente avec chaque terme d'erreur qu'il doit atténuer; cependant, toutes les erreurs n'ont pas le même impact sur l'observable. Une erreur située en dehors du cône de lumière causal de l'observable ne peut en aucun cas influencer la valeur attendue mesurée; et même à l'intérieur de ce cône, certaines erreurs sont plus préjudiciables que d'autres. Un cône de lumière ombré permet de quantifier cela en délimitant l'effet que chaque terme d'erreur de Pauli exerce sur l'observable. Le tronquage des termes d'erreur ayant l'effet le plus faible réduit la complexité du modèle de bruit que le PEC doit atténuer, ce qui diminue le coût d'échantillonnage en échange d'un biais faible et borné.

Pour découvrir comment mettre en place un workflow réaliste et l'exécuter sur du matériel quantique, consultez le tutoriel « Probabilistic error cancellation with shaded lightcones » (Annulation probabiliste des erreurs avec cônes de lumière ombrés) sur le site IBM Quantum Platform.


1. Préparer les données d'entrée pour SLC

Nous construisons ici un circuit d'Ising à champ transversal « trotterisé » de 6 qubits et choisissons une observable d' ZZ e à un seul qubit sur le qubit central.

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 = 6
circuit = trotter_ising_circuit(
    num_qubits, num_steps=2, rx_angle=np.pi / 16, rzz_angle=-np.pi / 2
)

# 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)

Output:

Observable: IIZIII
Output of the previous code cell

Le SLC opère sur les couches de portes à deux qubits du circuit, qui sont sujettes au bruit. Ici, nous utilisons samplomatic pour regrouper les portes dans des encadrés annotés et nous attribuons une annotation d'injection de bruit à chaque couche de deux qubits. generate_noise_model_paulis puis énumère les termes d'erreur de Pauli de chaque couche bruyante distincte.

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",
    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}")

Output:

Noisy layers: 2
Pauli error terms across all layers: 102

2. Calculer le cône de lumière ombré

Le cône de lumière ombré est construit en attribuant un coefficient à chaque terme d'erreur de Pauli du modèle de bruit, en fonction de l'importance de son effet sur la valeur attendue de l'observable. Ces échelles sont calculées à partir des limites d'erreur en avant et en arrière de chaque terme d'erreur (décrites ci-dessous), ainsi que de son taux d'erreur :

  • compute_forward_bounds fait évoluer chaque terme d'erreur jusqu'à la fin du circuit afin de limiter son effet sur l'observable qui y est mesurée.
  • compute_backward_bounds fait évoluer chaque terme d'erreur à rebours jusqu'au début du circuit afin de limiter son effet sur l'état initial.

merge_bounds combine les deux en un seul terme d'erreur. Fusion des échelles, chacune étant limitée par le taux d'erreur du terme. Ces taux proviennent généralement d'une expérience d'apprentissage du bruit (par exemple NoiseLearnerV3); Ici, par souci de simplicité, nous utilisons des taux aléatoires.

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
)

Dans la visualisation du cône de lumière ombré ci-dessous, chaque case est ombrée en fonction de l'importance avec laquelle les erreurs à cet emplacement peuvent affecter la grandeur observable : les cases claires correspondent aux limites les plus larges, tandis que les cases qui s'estompent vers l'arrière-plan contiennent des termes d'erreur qui ont peu d'effet sur le calcul — ces erreurs sont des candidates naturelles à exclure du modèle de bruit. Les valeurs indiquées dans la visualisation ci-dessous correspondent à la somme des limites d'erreur de toutes les erreurs de Pauli à cet emplacement; c'est pourquoi certaines de ces valeurs dépassent 2.0 -- la limite applicable à une erreur de Pauli isolée.

from qiskit_addon_slc.visualization import draw_shaded_lightcone

draw_shaded_lightcone(boxed_circuit, merged_bounds, noise_model_paulis)

Output:

Output of the previous code cell

3. Réduire le coût de l'échantillonnage

compute_local_scales transforme le cône de lumière ombré en une configuration PEC concrète. Elle classe les termes d'erreur par ordre de priorité en fonction de leur effet limité sur la grandeur observable et élimine ceux qui ont le moins d'impact jusqu'à ce que la valeur souhaitée bias_tolerance soit atteinte. Elle renvoie des coefficients pour chaque terme d'erreur : 0.0 pour les termes à ignorer lors de l'atténuation et -1.0 pour les termes qui doivent être atténués. La fonction renvoie également le surcoût d'échantillonnage qui en résulte ( γ2\gamma^2 ) ainsi qu'une borne sur le biais résiduel induit par la troncature.

Ce paramètre atténue bias_tolerance=0.0 chaque terme d'erreur au sein du cône de lumière causal de l'observable et fournit un coût d'échantillonnage de référence. En autorisant un léger biais, SLC peut écarter les termes à faible impact et réduire encore davantage ce coût.

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:.3f}, residual bias {full_bias:.3f}"
)
print(
    f"Shaded    (bias_tolerance=0.05): sampling cost {reduced_cost:.3f}, residual bias {reduced_bias:.3f}"
)
print(
    f"\nSampling-cost reduction: {(1 - reduced_cost / full_cost):.0%} for <= 0.05 bias"
)

Output:

Full PEC (bias_tolerance=0.0):  sampling cost 1.923, residual bias 0.000
Shaded    (bias_tolerance=0.05): sampling cost 1.441, residual bias 0.044

Sampling-cost reduction: 25% for <= 0.05 bias
Cette page a-t-elle été utile ?
Signaler un bogue, une coquille ou proposer du contenu sur GitHub.