동적 디커플링을 위한 패스 매니저 만들기
패키지 버전
이 페이지의 코드는 다음 요구 사항을 사용하여 개발되었습니다. 이 버전 이상을 사용하길 권장합니다.
qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1
이 페이지에서는 PadDynamicalDecoupling 패스를 사용하여 _동적 디커플링_이라고 불리는 오류 억제 기법을 Circuit에 추가하는 방법을 설명합니다.
동적 디커플링은 유휴 Qubit에 펄스 시퀀스(_동적 디커플링 시퀀스_라고 함)를 추가하여 Qubit을 블로흐 구면 주위로 뒤집음으로써 노이즈 채널의 영향을 상쇄하고 결어긋남을 억제하는 방식으로 작동합니다. 이러한 펄스 시퀀스는 핵자기공명에서 사용되는 재초점 펄스와 유사합니다. 자세한 설명은 A Quantum Engineer's Guide to Superconducting Qubits를 참조하세요.
PadDynamicalDecoupling 패스는 스케줄된 Circuit에서만 작동하며, 대상의 기저 Gate가 아닌 Gate를 포함하므로 ALAPScheduleAnalysis 및 BasisTranslator 패스도 함께 필요합니다.
이 예제에서는 사전에 초기화된 ibm_fez를 사용합니다. backend에서 target 정보를 가져오고 동작 이름을 basis_gates로 저장합니다. 이는 동적 디커플링에 사용되는 Gate에 대한 타이밍 정보를 추가하기 위해 target을 수정해야 하기 때문입니다.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-ibm-runtime
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
backend = service.backend("ibm_fez")
target = backend.target
basis_gates = list(target.operation_names)
예제로 efficient_su2 Circuit을 만듭니다. 먼저, 동적 디커플링 펄스는 Circuit이 트랜스파일되고 스케줄된 후에 추가해야 하므로 Circuit을 Backend에 맞게 트랜스파일합니다. 동적 디커플링은 양자 Circuit에 유휴 시간이 많을 때, 즉 다른 Qubit이 활성 상태인 동안 사용되지 않는 Qubit이 있을 때 가장 효과적으로 작동합니다. 이 Circuit에서는 2-Qubit ecr Gate가 이 앤사츠에서 순차적으로 적용되므로 이러한 상황이 발생합니다.
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.circuit.library import efficient_su2
qc = efficient_su2(12, entanglement="circular", reps=1)
pm = generate_preset_pass_manager(1, target=target, seed_transpiler=12345)
qc_t = pm.run(qc)
qc_t.draw("mpl", fold=-1, idle_wires=False)
동적 디커플링 시퀀스는 항등 행렬을 구성하고 시간적으로 일정한 간격으로 배치된 Gate의 연속입니다. 예를 들어, 네 개의 Gate로 구성된 XY4라는 간단한 시퀀스를 만들어 시작해 보겠습니다.
from qiskit.circuit.library import XGate, YGate
X = XGate()
Y = YGate()
dd_sequence = [X, Y, X, Y]
동적 디커플링 시퀀스의 규칙적인 타이밍 때문에 YGate에 대한 정보를 target에 추가해야 합니다. YGate는 기저 Gate가 아니지만 XGate는 기저 Gate입니다. 그러나 YGate는 XGate와 동일한 지속 시간과 오류를 가진다는 것을 사전에 알고 있으므로, target에서 해당 속성을 가져와 YGate 객체에 추가할 수 있습니다. 이것이 basis_gates를 별도로 저장한 이유이기도 합니다. YGate 명령어를 target에 추가하지만, 이는 실제로 ibm_fez의 기저 Gate가 아닙니다.
from qiskit.transpiler import InstructionProperties
y_gate_properties = {}
for qubit in range(target.num_qubits):
y_gate_properties.update(
{
(qubit,): InstructionProperties(
duration=target["x"][(qubit,)].duration,
error=target["x"][(qubit,)].error,
)
}
)
target.add_instruction(YGate(), y_gate_properties)
efficient_su2와 같은 앤사츠 Circuit은 매개변수화되어 있으므로, Backend로 전송하기 전에 값을 바인딩해야 합니다. 여기서는 임의의 매개변수를 할당합니다.
import numpy as np
rng = np.random.default_rng(1234)
qc_t.assign_parameters(
rng.uniform(-np.pi, np.pi, qc_t.num_parameters), inplace=True
)
다음으로, 사용자 정의 패스를 실행합니다. ALAPScheduleAnalysis와 PadDynamicalDecoupling을 사용하여 PassManager를 인스턴스화합니다. 규칙적인 간격의 동적 디커플링 시퀀스를 추가하기 전에 양자 Circuit에 대한 타이밍 정보를 추가하기 위해 먼저 ALAPScheduleAnalysis를 실행합니다. 이 패스들은 .run()을 통해 Circuit에서 실행됩니다.
from qiskit.transpiler import PassManager
from qiskit.transpiler.passes.scheduling import (
ALAPScheduleAnalysis,
PadDynamicalDecoupling,
)
dd_pm = PassManager(
[
ALAPScheduleAnalysis(target=target),
PadDynamicalDecoupling(target=target, dd_sequence=dd_sequence),
]
)
qc_dd = dd_pm.run(qc_t)
시각화 도구 timeline_drawer를 사용하여 Circuit의 타이밍을 확인하고 규칙적인 간격의 XGate 객체와 YGate 객체 시퀀스가 Circuit에 나타나는지 확인합니다.
from qiskit.visualization import timeline_drawer
timeline_drawer(qc_dd, idle_wires=False, target=target)
마지막으로, YGate는 Backend의 실제 기저 Gate가 아니므로 BasisTranslator 패스를 수동으로 적용합니다(이는 기본 패스이지만 스케줄링 전에 실행되므로 다시 적용해야 합니다). 세션 동치 라이브러리는 Transpiler가 Circuit을 기저 Gate로 분해할 수 있도록 하는 Circuit 동치 라이브러리이며, 이것도 인수로 지정됩니다.
from qiskit.circuit.equivalence_library import (
SessionEquivalenceLibrary as sel,
)
from qiskit.transpiler.passes import BasisTranslator
qc_dd = BasisTranslator(sel, basis_gates)(qc_dd)
qc_dd.draw("mpl", fold=-1, idle_wires=False)
이제 Circuit에서 YGate 객체가 없어지고, Delay Gate 형태의 명시적인 타이밍 정보가 포함됩니다. 동적 디커플링 이 적용된 이 트랜스파일된 Circuit은 이제 Backend로 전송할 준비가 되었습니다.
다음 단계
- 자체 패스를 작성하는 대신
generate_preset_passmanager함수를 사용하는 방법을 배우려면 Transpiler 기본 설정 및 구성 옵션 항목부터 시작하세요. - Transpiler 설정 비교 가이드를 사용해 보세요.
- Transpile API 문서를 참조하세요.