주 콘텐츠로 건너뛰기
이 프로젝트는 베타 단계입니다. 버그를 발견하셨나요? GitHub 이슈 만들기. 질문이나 아이디어가 있으신가요? Discussions에서 질문하기 — 피드백을 기다립니다!
이 페이지의 번역 품질은 어떻습니까?

속도 제한으로 경계를 강화하는 방법

두 큐비트 게이트로 이루어진 회로에서 정보는 임의로 빠르게 퍼질 수 없습니다. 끝에서 여러 층 앞서, 관측량의 지지 영역에서 멀리 떨어진 큐비트에서 발생한 오류는 관측량에 도달할 경로가 없습니다. tighten_with_speed_limit은 이러한 기하학적 논거(Lieb-Robinson 경계의 배경이 되는 것과 같은 직관)를 더 엄격한 순방향 경계로 바꿉니다.

이 단계는 비용이 적게 들고, 순방향 경계가 이미 요구한 것 외에는 아무것도 필요하지 않으며, 경계를 더 엄격하게만 만들 수 있습니다. 따져봐야 할 정확도 트레이드오프가 없습니다.

먼저 답해 볼 만한 질문은 *"언제 도움이 되는가?"*입니다. 완전히 수렴한 순방향 경계에서는 도움이 되는 경우가 많지 않기 때문입니다.

설정​

빠른 시작 가이드와 같은 Trotter화된 Ising 회로를 사용하며, 관측량은 체인 가운데의 단일 큐비트에 둡니다. 1D 기하 구조 덕분에 효과를 쉽게 추론할 수 있습니다. 영향은 층마다 결합 하나씩 체인을 가로질러야 합니다.

# 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
from qiskit_addon_slc.bounds import (
compute_forward_bounds,
tighten_with_speed_limit,
)
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

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
)

# A single-qubit observable in the middle of the chain.
observable = Pauli("I" * num_qubits).compose("Z", [num_qubits // 2])

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)
noise_model_paulis = generate_noise_model_paulis(
find_unique_box_instructions(boxed_circuit)
)

def compare(label, bounds):
"""Tightens a set of bounds and prints what changed."""
tightened = tighten_with_speed_limit(
bounds, boxed_circuit, noise_model_paulis, observable
)
before = np.concatenate([bound.rates for bound in bounds.values()])
after = np.concatenate([bound.rates for bound in tightened.values()])
print(
f"{label:30} mean {before.mean():.4f} -> {after.mean():.4f} "
f"tightened {np.count_nonzero(after < before - 1e-12):4} of {len(before)} "
f"loosened {np.count_nonzero(after > before + 1e-12)}"
)

print(
f"observable: Z on qubit {num_qubits // 2}, circuit depth {circuit.depth()}"
)
observable: Z on qubit 5, circuit depth 12

도움이 되는 경우와 그렇지 않은 경우​

tighten_with_speed_limit은 이미 가지고 있는 경계를 받아 강화된 사본을 반환하며, 원래 경계는 절대 수정되지 않습니다. 얼마나 개선되는지는 전적으로 입력이 얼마나 느슨했는지에 달려 있습니다.

# 1. Fully computed forward bounds.
full_bounds = compute_forward_bounds(
boxed_circuit, noise_model_paulis, observable
)
compare("fully computed", full_bounds)

# 2. Bounds where the eigenvalue step was skipped, leaving the looser triangle inequality.
loose_bounds = compute_forward_bounds(
boxed_circuit, noise_model_paulis, observable, eigval_max_qubits=0
)
compare("triangle inequality only", loose_bounds)

# 3. Bounds computed only for the first few boxes, the rest left at the trivial bound of 2.0.
shallow_bounds = compute_forward_bounds(
boxed_circuit, noise_model_paulis, observable, max_num_boxes=2
)
compare("max_num_boxes=2", shallow_bounds)
fully computed mean 0.3639 -> 0.3639 tightened 0 of 792 loosened 0
triangle inequality only mean 0.5081 -> 0.4842 tightened 105 of 792 loosened 0
max_num_boxes=2 mean 1.5707 -> 0.5284 tightened 450 of 792 loosened 0

주목해야 할 것은 첫 번째 줄입니다. 완전히 계산된 순방향 경계에서는 속도 제한이 아무것도 바꾸지 않습니다. 이는 실패가 아닙니다. 연산자 발전이 사실상 라이트콘을 스스로 찾아냈기 때문에, 경계가 이미 기하학적 논거로 증명할 수 있는 만큼 이상으로 엄격했다는 뜻입니다.

개선은 경계가 완전히 계산되지 않은 경우에 나타납니다.

  • eigval_max_qubits=0은 삼각 부등식 폴백을 강제하므로, 경계가 더 이상 교환자의 실제 스펙트럼 노름을 반영하지 않습니다. 속도 제한은 그 손실의 일부를 복구합니다.

  • max_num_boxes=2는 대부분의 층을 자명한 경계 2.0(아무 정보도 담지 않은 경계)으로 남겨 둡니다. 이 경우 속도 제한이 도움이 되어 평균을 대략 3분의 1로 줄입니다.

모든 경우에 "느슨해진" 열은 0입니다. 어떤 항도 나빠지지 않으며, 이것이 이 단계를 무조건 적용해도 안전하게 만드는 보장입니다.

샘플링 오버헤드에서 얻는 이점​

경계가 더 엄격하면 주어진 편향 허용치에 대해 완화해야 하는 오류 항이 줄어들며, 이는 하드웨어에서 중요한 수치입니다.

from qiskit.quantum_info import PauliLindbladMap, QubitSparsePauliList
from qiskit_addon_slc.bounds import compute_local_scales

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

tightened_shallow = tighten_with_speed_limit(
shallow_bounds, boxed_circuit, noise_model_paulis, observable
)

print(
f"{'bounds':30} {'overhead':>9} {'mitigated':>10} {'residual bias':>14}"
)
for label, bounds in (
("max_num_boxes=2", shallow_bounds),
("max_num_boxes=2 + speed limit", tightened_shallow),
("fully computed", full_bounds),
):
scales, cost, bias = compute_local_scales(
boxed_circuit, bounds, noise_rates, bias_tolerance=0.05
)
mitigated = sum(int(np.count_nonzero(scale)) for scale in scales.values())
total = sum(len(scale) for scale in scales.values())
print(
f"{label:30} {cost:9.4f} {f'{mitigated}/{total}':>10} {bias:>14.4f}"
)
bounds overhead mitigated residual bias
max_num_boxes=2 420.2823 617/792 0.0490
max_num_boxes=2 + speed limit 7.8511 226/792 0.0485
fully computed 5.4031 188/792 0.0494

언제 사용하나요​

순방향 경계가 완전히 수렴하지 않았을 때마다(본질적으로, 구성 가이드의 옵션을 사용해 정확도를 속도와 맞바꾼 경우마다) 적용하세요. 경계 계산에 비해 비용이 적게 들고, 아무것도 나쁘게 만들 수 없으며, max_num_boxes 또는 eigval_max_qubits 한도로 잃은 것의 상당 부분을 복구합니다.

완전히 계산된 경계에서는 아무 동작도 하지 않으므로 무조건 적용해도 해가 없습니다.

두 가지 제한 사항이 있습니다.

  • 순방향 경계에만 적용됩니다. 역방향 경계는 오류가 관측량이 아니라 초기 상태에 미치는 영향을 다루므로 이 논거가 그대로 적용되지 않습니다.

  • 관측량은 단일 Pauli 항이어야 합니다. 여러 항으로 이루어진 관측량의 경우 Pauli마다 한 번씩 호출하고 결과를 직접 결합하세요. 관측량이 단일 Pauli 항이 아니면 NotImplementedError가 발생합니다.

표준 워크플로에서는 빠른 시작 가이드에 나와 있듯이 순방향 경계를 계산한 후, 역방향 경계와 병합하기 전에 사용합니다.