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

게이트의 노이즈 모델 학습하기

이 튜토리얼은 고수준 프로토콜 함수 prepare_vanilla_program()과 process_vanilla_result()로 사용할 수 있는 표준 학습 프로토콜을 통해 유니터리 게이트의 노이즈 모델을 학습하는 방법을 보여 줍니다.

  1. 게이트 정의하기

  2. 로컬 시뮬레이션 설정하기

  3. 양자 프로그램 준비하기

  4. 양자 프로그램 실행하기

  5. 결과 읽기

실제 하드웨어에서 실행

아래 회로는 로컬에서 시뮬레이션되므로 이 안내를 따라 하는 데 IBM Quantum® 자격 증명이 필요하지 않습니다. 대신 실제 장치에서 실행하려면 다음과 같이 합니다.

  • 1단계: FakeMarrakesh를 실제 백엔드로 교체합니다.

  • 2단계: 해당 백엔드를 실행기(executor)의 모드로 전달하고 시뮬레이터 옵션은 제거합니다.

1. 게이트 정의하기​

이 게이트는 서로 겹치지 않는 CZ 게이트 6개로 이루어진 트윌링된 층을 담고 있는 BoxOp입니다.

from qiskit.circuit import QuantumCircuit
from qiskit_ibm_runtime.fake_provider import FakeMarrakesh
from samplomatic import InjectNoise, Tag, Twirl

backend = FakeMarrakesh()

cz_pairs = [(91, 92), (93, 94), (95, 99), (98, 111), (112, 113), (114, 115)]

circuit = QuantumCircuit(backend.num_qubits)
with circuit.box([Twirl(), Tag("cz_gate"), InjectNoise("cz_gate")]):
for pair in cz_pairs:
circuit.cz(*pair)
실제 하드웨어에서 실행
from qiskit_ibm_runtime import QiskitRuntimeService

backend = QiskitRuntimeService().backend("ibm_marrakesh")

2. 로컬 시뮬레이션 설정하기​

각 맵 안의 Pauli 인덱스는 Gate에 대해 국소적이며, 물리 Qubit 순서의 오름차순입니다.

cz_qubits = sorted({qubit for pair in cz_pairs for qubit in pair})
local = {qubit: index for index, qubit in enumerate(cz_qubits)}
local
{91: 0,
92: 1,
93: 2,
94: 3,
95: 4,
98: 5,
99: 6,
111: 7,
112: 8,
113: 9,
114: 10,
115: 11}

각 CZ 쌍에 상관된 ZZ 항과 더 약한 XX 항을 두고, 모든 곳에 단일 Qubit Z 항을 추가하여 노이즈를 정의합니다. 측정에는 Qubit마다 비트 플립 항이 붙습니다.

from qiskit.quantum_info import PauliLindbladMap

num_qubits = len(cz_qubits)

cz_noise = PauliLindbladMap.from_sparse_list(
[("ZZ", [local[a], local[b]], 8e-4) for a, b in cz_pairs]
+ [("XX", [local[a], local[b]], 4e-4) for a, b in cz_pairs]
+ [("Z", [index], 3e-4) for index in range(num_qubits)],
num_qubits=num_qubits,
)

readout_noise = PauliLindbladMap.from_sparse_list(
[("X", [index], 5e-3) for index in range(num_qubits)], num_qubits=num_qubits
)

측정이 학습할 박스를 만듭니다.

measurement = QuantumCircuit(backend.num_qubits, num_qubits)
with measurement.box([Twirl(), Tag("readout"), InjectNoise("readout")]):
for clbit, qubit in enumerate(cz_qubits):
measurement.measure(qubit, clbit)

layer_noise_model의 각 항목은 이러한 박스 중 하나와 그 박스에 적용할 맵을 짝지어 줍니다. 스태빌라이저 시뮬레이션 방법을 사용하고, seed_simulator를 설정하여 시뮬레이션 데이터를 재현 가능하게 만듭니다.

from qiskit_aer import AerSimulator
from qiskit_ibm_runtime import Executor

executor = Executor(
mode=AerSimulator(method="stabilizer"),
options={
"simulator": {
"layer_noise_model": [
(circuit[0], cz_noise),
(measurement[0], readout_noise),
],
"seed_simulator": 1234,
}
},
)
실제 하드웨어에서 실행
executor = Executor(mode=backend)

3. 양자 프로그램 준비하기​

prepare_vanilla_program()을 사용하여 학습 실험을 담은 양자 프로그램을 만듭니다.

from qiskit_noise_learning.protocols import prepare_vanilla_program

program = prepare_vanilla_program(
backend,
[circuit[0], measurement[0]],
fragment_depths=[2, 16, 64, 128],
num_randomizations=50,
shots_per_randomization=20,
)

print(f"Number of template circuits: {len(program.items)}")
Number of template circuits: 5

4. 양자 프로그램 실행하기​

양자 프로그램을 제출합니다. 이 단계는 executor가 시뮬레이터를 가리키든 실제 장치를 가리키든 동일합니다.

result = executor.run(program).result()

5. 결과 읽기​

process_vanilla_result()로 결과를 처리합니다.

from qiskit_noise_learning.protocols import process_vanilla_result

noise_maps, gate_names, fit = process_vanilla_result(result)

Qubit 쌍별 충실도 감쇠를 플롯합니다. 데이터와 지수 피팅을 모두 표시합니다.

fit.plot_qubit_pair_decays(
pairs=cz_pairs,
observable_type="means",
exponential_fit=True,
)