Paano higpitan ang mga bound gamit ang speed limit
Hindi basta-basta mabilis na kumakalat ang impormasyon sa isang circuit ng two-qubit gate. Ang error na nangyari
ilang layer bago ang dulo, sa qubit na malayo sa support ng observable, ay walang daan para marating
ito. Ginagawa ng tighten_with_speed_limit na mas mahigpit na forward bound ang geometric na argumentong iyon (ang parehong intuwisyon sa likod ng
mga Lieb-Robinson bound).
Mura ang hakbang na ito, walang kailangang higit sa kinailangan na ng mga forward bound, at maaari lang nitong gawing mas mahigpit ang mga bound. Walang trade-off sa katumpakan na dapat timbangin.
Ang tanong na dapat unang sagutin ay "kailan ito nakakatulong?", dahil madalas itong hindi nakakatulong sa isang ganap nang converged na set ng forward bound.
Pag-setup
Gamitin ang parehong Trotterized Ising circuit gaya ng quickstart guide, na ang observable ay sa iisang qubit sa gitna ng chain. Dahil sa 1D na geometry, madaling suriin ang epekto: kailangang tumawid ang isang impluwensya sa chain ng isang bond kada layer.
# 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
Kailan ito nakakatulong, at kailan hindi
Kinukuha ng tighten_with_speed_limit ang mga bound na mayroon ka na at nagbabalik ng pinahigpit na kopya; ang
orihinal mong mga bound ay hindi kailanman binabago. Kung gaano ito makakapagpabuti ay nakadepende nang buo sa kung gaano kaluwag ang input.
# 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
Ang unang linya ang dapat mapansin. Sa mga ganap na nakalkulang forward bound, walang binabago ang speed limit. Hindi ito pagkabigo. Ibig sabihin nito, kasing-higpit na ng maipapatunay ng geometric na argumento ang mga bound, dahil natuklasan na ng operator evolution ang light cone mag-isa.
Lumilitaw ang mga pakinabang kung saan hindi ganap na nakalkula ang mga bound:
-
Pinipilit ng
eigval_max_qubits=0ang triangle-inequality fallback, kaya hindi na sinasalamin ng mga bound ang aktwal na spectral norm ng commutator. Nababawi ng speed limit ang bahagi ng nawalang iyon. -
Iniiwan ng
max_num_boxes=2ang karamihan ng layer sa trivial na bound na 2.0 (isang bound na walang sinasabing impormasyon). Dito, nakakatulong ang speed limit, na binabawasan ang mean nang humigit-kumulang tatlong beses.
Sa bawat kaso, zero ang column na "loosened". Walang term na kailanman pinalala, na siyang garantiya kung bakit ligtas ilapat ang hakbang na ito nang walang kondisyon.
Ano ang nabibili nito sa sampling overhead
Ang mas mahigpit na mga bound ay nangangahulugan ng mas kaunting error term na kailangang i-mitigate para sa isang bias tolerance, na siyang numerong mahalaga sa hardware.
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
Kailan ito gagamitin
Ilapat ito sa mga forward bound tuwing hindi pa ganap na converged ang mga bound na iyon (sa madaling salita,
tuwing ipinagpalit mo ang katumpakan para sa bilis sa paggamit ng alinmang option sa
configuration guide). Mura ito kumpara sa pagkalkula ng mga bound,
hindi nito napalalala ang anuman, at nababawi nito ang karamihan sa isinuko ng limitasyong max_num_boxes o eigval_max_qubits.
Sa mga ganap na nakalkulang bound, wala itong ginagawa, kaya walang masama sa paglalapat nito nang walang kondisyon.
Dalawang limitasyon:
-
Para lang ito sa mga forward bound. Ang mga backward bound ay tungkol sa epekto ng error sa initial state at hindi sa observable, kaya hindi umaangkop ang argumento.
-
Ang observable ay dapat na iisang Pauli term. Para sa observable na maraming term, tawagin ito isang beses kada Pauli at pagsamahin mo mismo ang mga resulta. Kung hindi iisang Pauli term ang observable, magtataas ito ng
NotImplementedError.
Sa karaniwang workflow, nasa pagitan ito ng pagkalkula ng mga forward bound at pagsasama ng mga iyon sa mga backward bound, gaya ng ipinapakita ng quickstart guide.