Pular para o conteúdo principal
Este projeto está em fase beta. Encontrou um bug? Abra uma issue no GitHub. Tem uma pergunta ou ideia? Pergunte no Discussions — adoraríamos receber seu feedback!
Como está a qualidade da tradução nesta página?

Início rápido


title: Início rápido description: Um guia de início rápido para o addon Shaded lightcones do Qiskit (qiskit-addon-slc)​

Este guia demonstra um exemplo mínimo funcional do pacote qiskit-addon-slc. Ele calcula um cone de luz sombreado para reduzir o custo de amostragem do cancelamento probabilístico de erros (PEC).

O PEC mitiga o ruído das portas amostrando de uma decomposição em quasiprobabilidades do canal de ruído inverso. Seu custo de amostragem cresce a cada termo de erro que ele precisa mitigar; porém, nem todo erro afeta o observável da mesma forma. Um erro fora do cone de luz causal do observável não pode influenciar o valor esperado medido, e mesmo dentro do cone de luz, alguns erros são mais prejudiciais que outros. Um cone de luz sombreado quantifica isso limitando o efeito que cada termo de erro de Pauli tem sobre o observável. Truncar os termos de erro com o menor efeito reduz o modelo de ruído que o PEC precisa mitigar, diminuindo o custo de amostragem em troca de um viés pequeno e limitado.

Para ver como construir um fluxo de trabalho realista e executá-lo em hardware quântico, confira o tutorial Cancelamento probabilístico de erros com cones de luz sombreados no IBM Quantum Platform.

1. Prepare as entradas para o SLC​

Primeiro, construa um circuito de Ising de campo transverso com Trotter de 10 qubits e escolha um observável ZZ de um único qubit no qubit do meio.

# 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

O SLC opera sobre as camadas ruidosas de portas de dois qubits do circuito. Aqui usamos samplomatic para agrupar as portas em caixas anotadas e anexar uma anotação de injeção de ruído a cada camada de dois qubits. O SLC exige que toda caixa ruidosa tenha um modifier_ref único, o que inject_noise_strategy="individual_modification" fornece; com a estratégia padrão do samplomatic, os limites saem errados ou seu cálculo nunca termina. Então, generate_noise_model_paulis enumera os termos de erro de Pauli de cada camada 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. Calcule o cone de luz sombreado​

O cone de luz sombreado é montado atribuindo uma escala a cada termo de erro de Pauli no modelo de ruído com base em quanto efeito ele tem sobre o valor esperado do observável. Essas escalas são derivadas dos limites de erro direto e inverso de cada termo de erro (descritos abaixo), assim como de sua taxa de erro:

  • compute_forward_bounds evolui cada termo de erro para frente até o final do circuito para limitar seu efeito sobre o observável medido ali.

  • compute_backward_bounds evolui cada termo de erro para trás até o início do circuito para limitar seu efeito sobre o estado inicial.

merge_bounds combina os dois em um único limite por termo de erro. Cada limite é escalado pela taxa de erro do termo. Essas taxas normalmente vêm de um experimento de aprendizado de ruído (como NoiseLearnerV3); este guia usa taxas aleatórias por simplicidade.

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.

Na visualização do cone de luz sombreado abaixo, cada caixa é sombreada conforme a intensidade com que os erros naquele local podem afetar o observável. Caixas brilhantes carregam os maiores limites, enquanto caixas que se misturam ao fundo contêm termos de erro com pouco efeito sobre o cálculo -- esses erros são candidatos naturais a serem removidos do modelo de ruído. Os valores na visualização abaixo representam somas dos limites de erro de todos os erros de Pauli naquele local, e é por isso que alguns valores crescem além de 2.0, o limite para qualquer erro 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. Reduza o custo de amostragem​

compute_local_scales transforma o cone de luz sombreado em uma configuração concreta de PEC. Ele prioriza os termos de erro pelo seu efeito limitado sobre o observável e trunca os menos impactantes até que o bias_tolerance solicitado seja atingido. Ele retorna escalas para cada termo de erro: 0.0 para termos a ignorar durante a mitigação e -1.0 para termos que devem ser mitigados. A função também retorna o overhead de custo de amostragem resultante (γ2\gamma^2) e um limite para o viés residual incorrido pelo truncamento.

Definir bias_tolerance=0.0 mitiga todos os termos de erro dentro do cone de luz causal do observável e fornece um custo de amostragem de referência. Permitir um viés pequeno deixa o SLC descartar os termos de baixo impacto e reduzir ainda mais esse custo.

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