Sari la conținutul principal
Acest proiect este în versiune beta. Ai găsit o eroare? Deschide un issue pe GitHub. Ai o întrebare sau o idee? Întreabă în Discussions — ne-ar plăcea să aflăm părerea ta!
Cum este calitatea traducerii pe această pagină?

Cum să interpretezi vizualizările shaded lightcone

Pachetul oferă două moduri de a privi un shaded lightcone:

  • draw_shaded_lightcone suprapune limitele peste diagrama circuitului. Este cel mai potrivit pentru circuite pe un lanț 1D de qubiți, unde diagrama circuitului și aranjamentul fizic coincid.

  • animate_shaded_lightcone proiectează limitele pe harta de cuplare a QPU și parcurge circuitul strat cu strat. Este cel mai potrivit când conectivitatea qubiților este mai mult decât o linie 1D, unde o diagramă a circuitului nu mai arată care qubiți sunt vecini.

Ambele vizualizări arată aceleași numere de bază. Acest ghid explică ce înseamnă acele numere și detaliile care sunt ușor de interpretat greșit.

Configurare​

Folosește același circuit Ising Trotterizat și aceeași observabilă ca ghidul de pornire rapidă.

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

Fiecare box zgomotos este umbrit după limita erorilor care apar acolo: luminos înseamnă o limită mare, iar un box care se estompează în fundal înseamnă că erorile sale au un efect mic asupra observabilei. Acele box-uri estompate sunt candidații pentru eliminarea din modelul de zgomot atenuat.

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

Note importante​

1. Fiecare număr este o sumă peste termenii de eroare care au același suport. Fără filtru, limitele tuturor termenilor de eroare care acționează pe același qubit, sau pe aceeași pereche de qubiți, sunt adunate într-o singură valoare: toate cele trei tipuri Pauli pe un qubit și toate cele nouă pe o pereche. Aceasta are două consecințe. O valoare poate depăși 2.0, deși limita niciunui termen singur nu poate (un box etichetat 4.5 este mai mulți termeni adunați, nu o limită încălcată). Figura nu îți poate spune dacă o valoare mare provine dintr-un singur tip Pauli sau din mai multe comparabile; secțiunea următoare arată cum le poți separa.

2. Scala de culori începe de la 2.0 și crește odată cu datele. Scala merge de la 0 la intrarea "max_bound" din metadatele circuitului suprapus, care este cea mai mare dintre 2.0 și cea mai mare valoare afișată. Sumele nefiltrate depășesc adesea 2.0, deci scala se întinde pentru a le cuprinde, iar aceeași culoare poate reprezenta valori diferite în figuri diferite. Când toate valorile sunt mici, scala rămâne la 2.0 și totul pare uniform întunecat (aceasta este scala care reflectă dimensiunea absolută, nu o defecțiune de randare).

Separarea tipurilor Pauli​

Folosește pauli_filter pentru a vedea câte un tip pe rând. Un număr întreg selectează o pondere Pauli; un șir selectează o anumită Pauli, potrivită cu fiecare termen de zgomot redus la propriul suport non-identitate. Astfel "X" selectează fiecare eroare XX pe un singur qubit, indiferent pe ce qubit acționează, iar "XX" selectează cele de pondere 2 (o etichetă pe toată lățimea, precum "XII", nu se potrivește cu nimic).

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}

Rândul nefiltrat este suma celor trei tipuri Pauli de sub el. Filtrarea este singura cale de a afla dacă o valoare mare nefiltrată provine dintr-un tip de eroare dominant sau din mai multe comparabile. Asta contează, deoarece atenuarea acționează per termen, nu per loc.

Transmiterea aceluiași filtru către draw_shaded_lightcone îl înregistrează în titlul figurii, astfel încât o figură filtrată să nu poată fi confundată cu una nefiltrată:

draw_shaded_lightcone(
boxed_circuit,
merged_bounds,
noise_model_paulis,
pauli_filter="X",
fold=-1,
scale=0.5,
)

Output of the previous code cell

Această figură arată destul de diferit de cea nefiltrată de mai sus, și nu doar pentru că arată mai puține valori. Fiecare placeholder din aceste figuri reprezintă un suport: un singur qubit sau o pereche de qubiți. Fără filtru, un box arată un placeholder pe fiecare qubit și pe fiecare pereche de qubiți vecini, așa că se întinde pe mai multe coloane. Cu "X" rămân doar suporturile pe un singur qubit, iar fiecare box se restrânge la o singură coloană.

Totuși, niciuna dintre imagini nu arată ce aplică de fapt PEC. Marcajele de poziție sunt o modalitate de a afișa limitele, nu porți anti-zgomot. În timpul experimentului, fiecare casetă ai cărei termeni de eroare sunt atenuați este tratată ca un singur strat de porți cu doi qubiți, iar Pauli-ii anti-zgomot eșantionați pentru termenii săi de eroare sunt compuși într-un singur Pauli care se aplică acelui strat în ansamblu.

animate_shaded_lightcone​

Pe un dispozitiv a cărui conectivitate nu este o linie 1D, o diagramă de circuit nu mai arată care qubiți sunt vecini, astfel încât răspândirea spațială a conului de lumină devine imposibil de citit. animate_shaded_lightcone desenează în schimb harta de cuplare a QPU și animează limitele pe ea, o casetă zgomotoasă pe cadru.

Are nevoie de un CouplingMap, pe care îl dispune pe o grilă prin încorporarea grafului dispozitivului, astfel încât gestionează atât conectivitatea heavy-hex, cât și pe cea pătrată.

Notă: În această documentație randată animația este statică. Cursorul și butonul de redare funcționează doar când notebook-ul rulează interactiv, de exemplu în Jupyter.

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)

Output of the previous code cell

Citirea animației​

Fiecare qubit este o diagramă circulară, câte o felie pentru fiecare tip de Pauli. Marcajul unui qubit este împărțit în trei felii pentru erorile sale XX, YY și ZZ, fiecare umbrită după propria limită. Aceasta este filtrarea din secțiunea anterioară integrată în figură (nu este nevoie de pauli_filter pentru a distinge tipurile).

Muchiile poartă limitele erorilor cu doi qubiți. Linia dintre doi qubiți cuplați este umbrită după limita erorilor de pondere 2 care acționează asupra acelei perechi.

Gri deschis înseamnă lipsa datelor, nu o limită mică. O felie sau o muchie este desenată în gri deschis atunci când modelul de zgomot al casetei nu are niciun termen de eroare pentru ea, de exemplu pentru qubiții asupra cărora caseta nu acționează. Este desenată în gri, nu în culoare închisă, pentru a nu fi confundată cu o limită egală cu zero. Casetele de peste limita max_num_boxes sunt diferite: ele au limita trivială de 2.0, deci sunt desenate la capătul strălucitor al scalei.

Cursorul parcurge casetele, nu timpul în mod uniform. Există un cadru pentru fiecare casetă zgomotoasă, în ordinea circuitului (sau în ordine inversă cu reverse=True, care urmărește conul de lumină înapoi de la observabilă). Vizionarea în ordine inversă este de obicei direcția mai intuitivă: conul crește dinspre qubiții măsurați spre exterior. Fiecare cadru este etichetat cu identificatorul casetei sale, aceeași cheie sub care dicționarul de limite stochează acea casetă, astfel încât cursorul poate fi folosit și pentru a sări la o casetă anume și a-i căuta valorile.

Notă: Dispunerea qubiților este recuperată din graful hărții de cuplare prin încorporarea lui într-o rețea pătrată. O hartă de cuplare care nu se poate încorpora (pentru că este deconectată sau prea dens conectată pentru o grilă) generează un ValueError în loc să deseneze o imagine înșelătoare.

Pe care să o folosești​

draw_shaded_lightconeanimate_shaded_lightcone
geometriediagrama circuituluiharta de cuplare a QPU
ideal pentrulanțuri 1Dorice conectivitate
tipuri de Pauliînsumate, dacă nu sunt filtratemereu separate, ca felii
timptoate straturile deodatăun strat pe cadru
ieșireo figură matplotlibo figură plotly

Pentru un lanț 1D, figura statică este mai ușor de cuprins dintr-o privire și se reproduce într-o lucrare. Dincolo de 1D, animația este singura dintre cele două care arată fidel structura spațială.