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

shaded lightcone 시각화를 해석하는 방법

이 패키지는 shaded lightcone을 보는 두 가지 방법을 제공합니다.

  • draw_shaded_lightcone은 경계값을 회로 다이어그램 위에 겹쳐 표시합니다. 회로 다이어그램과 물리적 배치가 일치하는 1D 큐비트 체인의 회로에 가장 적합합니다.

  • animate_shaded_lightcone은 경계값을 QPU의 커플링 맵에 투영하고 회로를 레이어별로 단계적으로 보여 줍니다. 큐비트 연결이 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, 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​

노이즈가 있는 각 박스는 그곳에서 발생하는 오류의 경계값에 따라 음영이 칠해집니다. 밝을수록 경계값이 크고, 박스가 배경 속으로 흐려지면 그 오류가 관측량에 미치는 영향이 작다는 뜻입니다. 이렇게 흐려진 박스들이 완화된 노이즈 모델에서 제외할 후보입니다.

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

중요한 참고 사항​

1. 각 숫자는 같은 지지 집합을 공유하는 오류 항들의 합입니다. 필터가 없으면 같은 큐비트 또는 같은 큐비트 쌍에 작용하는 모든 오류 항의 경계값이 하나의 값으로 더해집니다. 큐비트 하나에는 세 가지 파울리 유형이 모두, 쌍에는 아홉 가지가 모두 포함됩니다. 여기에는 두 가지 결과가 따릅니다. 어떤 단일 항의 경계값도 2.0을 넘을 수 없는데도 값이 2.0을 넘을 수 있습니다(4.5라고 표시된 박스는 경계값 위반이 아니라 여러 항이 더해진 것입니다). 또한 이 그림만으로는 큰 값이 하나의 파울리 유형에서 오는지, 비슷한 크기의 여러 유형에서 오는지 알 수 없습니다. 다음 섹션에서 이를 분리하는 방법을 보여 줍니다.

2. 색상 척도는 2.0에서 시작하며 데이터에 따라 커집니다. 척도는 0부터, 겹쳐 그린 회로의 메타데이터에 있는 "max_bound" 항목까지이며, 이는 2.0과 표시된 최댓값 중 큰 쪽입니다. 필터링하지 않은 합은 흔히 2.0을 넘으므로 척도가 이에 맞게 늘어나고, 같은 색이 그림마다 다른 값을 나타낼 수 있습니다. 모든 값이 작으면 척도는 2.0으로 유지되어 모든 것이 균일하게 어두워 보입니다(이는 렌더링 오류가 아니라 절대적인 크기를 반영하는 척도입니다).

파울리 유형 분리하기​

pauli_filter를 사용하면 한 번에 한 유형씩 볼 수 있습니다. 정수는 파울리 가중치를 선택하고, 문자열은 자체의 비항등 지지 집합으로 줄인 각 노이즈 항과 대조하여 특정 파울리를 선택합니다. 따라서 "X"는 어떤 큐비트에 작용하는지와 관계없이 모든 단일 큐비트 XX 오류를 선택하고, "XX"는 가중치 2인 것을 선택합니다("XII" 같은 전체 너비 레이블은 아무것도 일치하지 않습니다).

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}

필터링하지 않은 행은 그 아래 세 가지 파울리 유형의 합입니다. 필터링은 필터링하지 않은 큰 값이 하나의 지배적인 오류 유형에서 오는지 비슷한 크기의 여러 유형에서 오는지 구별하는 유일한 방법입니다. 완화가 사이트별이 아니라 항별로 작용하므로 이는 중요합니다.

같은 필터를 draw_shaded_lightcone에 전달하면 그림 제목에 기록되므로, 필터링된 그림을 필터링하지 않은 그림으로 오해할 수 없습니다.

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

Output of the previous code cell

이 그림은 위의 필터링하지 않은 그림과 상당히 달라 보이는데, 단지 값이 더 적게 표시되어서만은 아닙니다. 이 그림들의 각 플레이스홀더는 하나의 지지 집합, 즉 큐비트 하나 또는 큐비트 쌍을 나타냅니다. 필터가 없으면 박스에는 모든 큐비트와 이웃한 모든 큐비트 쌍에 대한 플레이스홀더가 표시되어 여러 열에 걸쳐 퍼집니다. "X"를 사용하면 단일 큐비트 지지 집합만 남고, 각 박스는 한 열로 줄어듭니다.

하지만 두 그림 모두 PEC가 실제로 적용하는 것을 보여주지는 않습니다. 플레이스홀더는 경계를 표시하기 위한 방법일 뿐, 노이즈 방지 게이트가 아닙니다. 실험 중에는 오류 항이 완화되는 각 박스를 두 큐비트 게이트의 단일 층으로 취급하며, 해당 오류 항에 대해 샘플링된 노이즈 방지 Pauli들은 하나의 Pauli로 합성되어 그 층 전체에 적용됩니다.

animate_shaded_lightcone​

연결성이 1D 선형이 아닌 장치에서는 회로도만으로는 어떤 큐비트가 서로 이웃인지 더 이상 알 수 없어서, 라이트콘의 공간적 확산을 읽을 수 없게 됩니다. 대신 animate_shaded_lightcone은 QPU의 커플링 맵을 그리고, 노이즈가 있는 박스 하나를 한 프레임으로 하여 그 위에서 경계를 애니메이션으로 보여줍니다.

이 함수는 CouplingMap이 필요하며, 장치 그래프를 임베딩하여 격자 위에 배치하므로 heavy-hex 연결성과 정사각형 연결성을 모두 처리할 수 있습니다.

참고: 렌더링된 이 문서에서는 애니메이션이 정적으로 표시됩니다. 슬라이더와 재생 버튼은 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

애니메이션 읽는 법​

각 큐비트는 파이 차트이며, Pauli 유형마다 한 조각씩입니다. 큐비트의 마커는 XX, YY, ZZ 오류를 나타내는 세 조각으로 나뉘고, 각 조각은 자신의 경계에 따라 음영이 칠해집니다. 이는 이전 섹션의 필터링이 그림에 내장된 것입니다(유형을 구분하기 위해 pauli_filter가 필요하지 않습니다).

간선은 두 큐비트 오류 경계를 나타냅니다. 커플링된 두 큐비트 사이의 선은 그 쌍에 작용하는 가중치 2 오류의 경계에 따라 음영이 칠해집니다.

밝은 회색은 작은 경계가 아니라 데이터가 없음을 뜻합니다. 박스의 노이즈 모델에 해당 오류 항이 없는 경우(예: 박스가 작용하지 않는 큐비트)에는 조각이나 간선이 밝은 회색으로 그려집니다. 경계가 0인 것과 혼동되지 않도록 어두운 색이 아닌 회색으로 그립니다. max_num_boxes 한도를 넘는 박스는 다릅니다. 이 박스들은 자명한 경계인 2.0을 가지므로 척도의 밝은 쪽 끝에 그려집니다.

슬라이더는 시간을 균일하게 따라가는 것이 아니라 박스를 하나씩 넘깁니다. 노이즈가 있는 박스마다 한 프레임이 있으며, 회로 순서대로(또는 reverse=True를 쓰면 역순으로, 즉 관측량에서 거슬러 올라가며 라이트콘을 추적) 진행됩니다. 역순으로 보는 것이 보통 더 직관적입니다. 측정된 큐비트에서부터 원뿔이 바깥으로 커지기 때문입니다. 각 프레임에는 해당 박스의 식별자가 표시되며, 이는 경계 딕셔너리가 그 박스를 저장하는 키와 같으므로 슬라이더로 특정 박스로 이동해 그 수치를 조회할 수도 있습니다.

참고: 큐비트 레이아웃은 커플링 맵의 그래프를 정사각 격자에 임베딩하여 복원합니다. 임베딩할 수 없는 커플링 맵(연결되어 있지 않거나 격자에 맞추기에는 너무 조밀하게 연결된 경우)은 오해를 부를 수 있는 그림을 그리는 대신 ValueError를 발생시킵니다.

어떤 것을 사용할까요​

draw_shaded_lightconeanimate_shaded_lightcone
기하 구조회로도QPU 커플링 맵
적합한 경우1D 체인모든 연결성
Pauli 유형필터링하지 않으면 합산항상 파이 조각으로 분리
시간모든 층을 한 번에프레임당 한 층
출력matplotlib 그림plotly 그림

1D 체인에서는 정적 그림이 한눈에 파악하기 쉽고 논문에 재현하기도 좋습니다. 1D를 넘어서는 경우에는 두 가지 중 애니메이션만이 공간 구조를 충실하게 보여줍니다.