Jak interpretovat vizualizace stínovaných světelných kuželů
Balíček nabízí dva způsoby, jak se na stínovaný světelný kužel podívat:
-
draw_shaded_lightconepřekryje meze přes diagram obvodu. To je nejvhodnější pro obvody na 1D řetězci qubitů, kde se diagram obvodu a fyzické uspořádání shodují. -
animate_shaded_lightconepromítne meze na mapu propojení QPU a prochází obvod vrstvu po vrstvě. To je nejvhodnější, když je konektivita qubitů víc než 1D přímka, kde diagram obvodu přestává vyjadřovat, které qubity jsou sousedé.
Obě vizualizace ukazují stejná základní čísla. Tento průvodce vysvětluje, co tato čísla znamenají, a rozebírá detaily, které se snadno špatně pochopí.
Nastavení
Použij stejný trotterizovaný Isingův obvod a pozorovatelnou jako rychlý úvod.
# 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, PauliLindbladMap, QubitSparsePauliList
from qiskit_addon_slc.bounds import (
compute_backward_bounds,
compute_forward_bounds,
merge_bounds,
)
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
)
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)
)
forward_bounds = compute_forward_bounds(
boxed_circuit, noise_model_paulis, observable
)
backward_bounds = compute_backward_bounds(boxed_circuit, noise_model_paulis)
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()
}
merged_bounds = merge_bounds(
boxed_circuit, forward_bounds, backward_bounds, noise_rates
)
print(f"observable: Z on qubit {num_qubits // 2}")
Optimal spacetime partitioning not implemented! Just partitioning list of noisy boxes.
observable: Z on qubit 5
draw_shaded_lightcone
Každý zašuměný box je vystínován podle meze chyb, které tam vznikají: jasný znamená velkou mez a box splývající s pozadím znamená, že jeho chyby mají na pozorovatelnou malý vliv. Tyto vybledlé boxy jsou kandidáty na vypuštění z modelu šumu použitého pro mitigaci.
from qiskit_addon_slc.visualization import draw_shaded_lightcone
draw_shaded_lightcone(
boxed_circuit, merged_bounds, noise_model_paulis, fold=-1, scale=0.5
)

Důležité poznámky
1. Každé číslo je součet přes členy chyb se společným nosičem. Bez filtru se meze
všech členů chyb působících na stejný qubit nebo na stejný pár qubitů sečtou do jedné hodnoty:
všechny tři typy Pauliho členů na qubitu a všech devět na páru. To má dva důsledky. Hodnota může
přesáhnout 2.0, přestože mez žádného jednotlivého členu nemůže (box označený 4.5 je součet několika členů,
ne porušená mez). Obrázek ti také neřekne, zda velká hodnota pochází z jednoho Pauliho
typu, nebo z několika srovnatelných; další část ukazuje, jak je oddělit.
2. Barevná škála začíná na 2.0 a roste s daty. Škála běží od 0 k
položce "max_bound" v metadatech překrytého obvodu, což je větší z 2.0 a největší
zobrazené hodnoty. Nefiltrované součty často přesahují 2.0, takže se škála roztáhne, aby je pojala, a tatáž
barva může v různých obrázcích znamenat různé hodnoty. Když jsou všechny hodnoty malé,
škála zůstává na 2.0 a vše vypadá rovnoměrně tmavě (to je škála odrážející absolutní
velikost, ne chyba vykreslování).
Oddělení Pauliho typů
Použij pauli_filter, abys viděl vždy jeden typ. Celé číslo vybírá Pauliho váhu; řetězec vybírá
konkrétní Pauliho člen, porovnávaný s každým šumovým členem zredukovaným na jeho vlastní nosič bez identity. Takže
"X" vybere každou jednoqubitovou chybu bez ohledu na to, na který qubit působí, a "XX" vybere
ty s váhou 2 (označení plné šířky jako "XII" nevybere nic).
from qiskit_addon_slc.visualization import accumulate_filtered_bounds
box_id = next(iter(merged_bounds))
print(f"single-qubit supports of box {box_id!r}:\n")
print(f"{'filter':>8} bounds per qubit")
for pauli_filter in (None, 1, "X", "Y", "Z"):
filtered = accumulate_filtered_bounds(
boxed_circuit, merged_bounds, noise_model_paulis, pauli_filter
)
per_qubit = {
support[0]: round(float(bound), 3)
for support, bound in sorted(filtered[box_id].items())
if len(support) == 1
}
print(f"{pauli_filter!s:>8} {per_qubit}")
single-qubit supports of box 'm0':
filter bounds per qubit
None {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.312, 4: 1.355, 5: 5.111, 6: 1.506, 7: 0.124, 8: 0.019, 9: 0.0}
1 {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.312, 4: 1.355, 5: 5.111, 6: 1.506, 7: 0.124, 8: 0.019, 9: 0.0}
X {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.153, 4: 0.577, 5: 2.0, 6: 0.702, 7: 0.056, 8: 0.01, 9: 0.0}
Y {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.148, 4: 0.607, 5: 2.0, 6: 0.631, 7: 0.057, 8: 0.01, 9: 0.0}
Z {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.011, 4: 0.172, 5: 1.111, 6: 0.172, 7: 0.011, 8: 0.0, 9: 0.0}
Nefiltrovaný řádek je součtem tří Pauliho typů pod ním. Filtrování je jediný způsob, jak zjistit, zda velká nefiltrovaná hodnota pochází z jednoho dominantního typu chyby, nebo z několika srovnatelných. To je důležité, protože mitigace působí na člen, ne na místo.
Předání stejného filtru do draw_shaded_lightcone jej zaznamená do titulku obrázku, takže filtrovaný
obrázek nelze splést s nefiltrovaným:
draw_shaded_lightcone(
boxed_circuit,
merged_bounds,
noise_model_paulis,
pauli_filter="X",
fold=-1,
scale=0.5,
)

Tento obrázek vypadá docela jinak než nefiltrovaný výše, a nejen proto, že ukazuje
méně hodnot. Každý zástupný symbol na těchto obrázcích představuje jeden nosič: jeden qubit nebo pár
qubitů. Bez filtru box ukazuje zástupný symbol na každém qubitu a na každém páru sousedních
qubitů, takže se rozprostírá přes několik sloupců. S "X" zůstanou jen jednoqubitové nosiče a
každý box se zúží do jediného sloupce.
Ani jeden z obrázků však neukazuje, co PEC skutečně aplikuje. Zástupné symboly jsou způsob, jak zobrazit meze, nikoli anti-šumová hradla. Během experimentu se každý box, jehož chybové členy jsou mitigovány, považuje za jedinou vrstvu dvouqubitových hradel a anti-šumové Pauliho operátory vzorkované pro jeho chybové členy se složí do jednoho Pauliho operátoru, který se aplikuje na celou tuto vrstvu.
animate_shaded_lightcone
Na zařízení, jehož konektivita není 1D linie, diagram obvodu již neukazuje, které qubity spolu sousedí, takže prostorové šíření světelného kužele nelze z diagramu vyčíst. animate_shaded_lightcone místo toho vykreslí coupling map QPU a animuje na ní meze, jeden zašuměný box na snímek.
Vyžaduje CouplingMap, který rozloží do mřížky vnořením grafu zařízení, takže zvládá jak konektivitu heavy-hex, tak čtvercovou.
Poznámka: V této vykreslené dokumentaci je animace statická. Posuvník a tlačítko přehrávání fungují pouze při interaktivním spuštění notebooku, například v Jupyteru.
from qiskit import transpile
from qiskit.transpiler import CouplingMap
from qiskit_addon_slc.visualization import animate_shaded_lightcone
# A small square-lattice device stands in for a real backend here.
coupling_map = CouplingMap.from_grid(3, 4)
# Lay the chain onto a connected path of physical qubits, snaking through the grid, so the
# transpiler inserts no SWAPs: a SWAP-laden circuit is far more expensive to bound and harder to
# read.
initial_layout = [0, 1, 2, 3, 7, 6, 5, 4, 8, 9]
device_circuit = transpile(
circuit,
coupling_map=coupling_map,
initial_layout=initial_layout,
optimization_level=0,
)
boxed_device_circuit = boxing_pass.run(device_circuit)
device_noise_paulis = generate_noise_model_paulis(
find_unique_box_instructions(boxed_device_circuit),
coupling_map=coupling_map,
circuit=boxed_device_circuit,
)
# The same observable, on the physical qubit the middle of the chain was laid onto.
device_observable = Pauli("I" * device_circuit.num_qubits).compose(
"Z", [initial_layout[num_qubits // 2]]
)
device_bounds = compute_forward_bounds(
boxed_device_circuit, device_noise_paulis, device_observable
)
animate_shaded_lightcone(boxed_device_circuit, device_bounds, coupling_map)

Jak číst animaci
Každý qubit je koláčový graf s jedním výsečí na typ Pauliho operátoru. Značka qubitu je rozdělena na tři výseče pro chyby , a , z nichž každá je zbarvena podle vlastní meze. Je to filtrování z předchozí části zabudované přímo do obrázku (k rozlišení typů není potřeba pauli_filter).
Hrany nesou meze dvouqubitových chyb. Čára mezi dvěma propojenými qubity je zbarvena podle meze chyb váhy 2 působících na tuto dvojici.
Světle šedá znamená žádná data, nikoli malou mez. Výseč nebo hrana se kreslí světle šedě, když model šumu boxu pro ni nemá žádný chybový člen, například u qubitů, na které box nepůsobí. Je šedá, a ne tmavá, aby se nedala splést s mezí nula. Boxy za limitem max_num_boxes jsou jiné: mají triviální mez 2,0, a proto se kreslí na světlém konci stupnice.
Posuvník prochází boxy, nikoli rovnoměrně časem. Na každý zašuměný box připadá jeden snímek, v pořadí obvodu (nebo v opačném pořadí s reverse=True, které sleduje světelný kužel zpětně od observable). Sledovat ho v opačném pořadí je obvykle intuitivnější: kužel se rozšiřuje směrem ven od měřených qubitů. Každý snímek je označen identifikátorem svého boxu, tedy stejným klíčem, pod kterým slovník mezí tento box uchovává, takže posuvník lze použít i k přeskočení na konkrétní box a vyhledání jeho čísel.
Poznámka: Rozložení qubitů se získá z grafu coupling map jeho vnořením do čtvercové mřížky. Coupling map, který se nevnoří (protože je nesouvislý nebo příliš hustě propojený pro mřížku), vyvolá ValueError, místo aby se vykreslil zavádějící obrázek.
Který použít
draw_shaded_lightcone | animate_shaded_lightcone | |
|---|---|---|
| geometrie | diagram obvodu | coupling map QPU |
| nejvhodnější pro | 1D řetězce | libovolnou konektivitu |
| typy Pauliho operátorů | sečtené, pokud nejsou filtrovány | vždy rozdělené jako koláčové výseče |
| čas | všechny vrstvy najednou | jedna vrstva na snímek |
| výstup | obrázek matplotlib | obrázek plotly |
Pro 1D řetězec je statický obrázek snazší na první pohled a dá se reprodukovat v článku. Mimo 1D je animace jediná z obou, která věrně ukazuje prostorovou strukturu.