사용자 정의 트랜스파일러 패스 작성
이 페이지의 코드는 다음 요구 사항을 사용하여 개발되었습니다. 다음 버전 이상을 사용하는 것이 좋습니다.
qiskit[all]~=2.5.2
키스킷 SDK를 사용하면 사용자 지정 트랜스파일레이션 패스를 생성하여 PassManager 객체에서 실행하거나 StagedPassManager 에 추가할 수 있습니다. 여기서는 양자 회로에서 잡음이 많은 양자 게이트에서 폴리 회전을 수행하는 패스를 구축하는 데 중점을 두고 트랜스파일러 패스를 작성하는 방법을 보여드리겠습니다. 이 예제에서는 TransformationPass 유형의 패스로 조작되는 객체인 DAG를 사용합니다.
패스를 구축하기 전에 키스킷에서 양자 회로의 내부 표현인 방향성 비순환 그래프(DAG )를 소개하는 것이 중요합니다(개요는 이 튜토리얼을 참조하세요). 다음 단계를 수행하려면 DAG 플로팅 함수용
graphviz라이브러리를 설치합니다.Qiskit에서는 트랜스파일레이션 단계 내에서 회로가 DAG(방향성 비순환 그래프)를 사용하여 표현됩니다. 일반적으로 DAG는 정점 (노드라고도 함)과 특정 방향으로 정점 쌍을 연결하는 방향성 변으로 구성됩니다. 이 표현은 개별
DagNode객체들로 구성된 객체들을qiskit.dagcircuit.DAGCircuit사용하여 저장됩니다. 이 표현 방식이 순수한 게이트 목록(즉, 네트리스트 )에 비해 갖는 장점은 연산 간 정보 흐름이 명시적으로 드러나 변환 결정을 내리기 쉽다는 점이다.이 예는 벨 상태를 준비하고 측정 결과에 따라 회전을 적용하는 간단한 회로를 생성하여 DAG를 설명합니다.
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit import numpy as np qr = QuantumRegister(3, 'qr') cr = ClassicalRegister(3, 'cr') qc = QuantumCircuit(qr, cr) qc.h(qr[0]) qc.cx(qr[0], qr[1]) qc.measure(qr[0], cr[0]) with qc.if_test((cr, 2)): qc.rz(np.pi/2, qr[1]) qc.draw(output='mpl')
회로 qiskit.tools.visualization.dag_drawer()함수를 사용하여 이 회로의 DAG를 확인합니다. 그래프 노드에는 쿼비트/클릭비트 노드(녹색), 연산 노드(파란색), 출력 노드(빨간색)의 세 가지 종류가 있습니다. 각 에지는 두 노드 간의 데이터 흐름(또는 종속성)을 나타냅니다.from qiskit.converters import circuit_to_dag from qiskit.visualization import dag_drawer dag = circuit_to_dag(qc) dag_drawer(dag)
DAG
트랜스파일러 통과
트랜스파일러 패스는 또는 AnalysisPass 로 분류됩니다 TransformationPass. 패스는 일반적으로 DAG 및 분석 패스에 의해 결정된 속성을 저장하기 위한 사전 property_set(dictionary)과 유사한 객체인 와 함께 작동합니다. 분석 패스는 DAG와 그 property_set. 모두에서 작동합니다. 그들은 DAG를 수정할 수는 없지만,. property_set을 수정할 수는 있습니다. 이는 DAG를 수정하는 변환 패스와는 대조적이며, DAG를 읽을 수는 있지만(쓰기는 불가능합니다) property_set. 예를 들어, 변환 단계에서는 회로를 해당 ISA로 변환하거나, 필요한 곳에 SWAP 게이트를 삽입하기 위해 배선 단계를 수행합니다.
트랜스파일러 PauliTwirl 패스 생성
다음 예제는 폴리 트위클을 추가하는 트랜스파일러 패스를 구성하는 예제입니다. 폴리 트위링은 큐비트가 잡음 채널을 경험하는 방식을 무작위로 변경하는 오류 억제 전략으로, 이 예에서는 2큐비트 게이트로 가정합니다(단일 큐비트 게이트보다 훨씬 오류가 발생하기 쉽기 때문입니다). 폴리 회전은 2큐비트 게이트의 작동에 영향을 미치지 않습니다. 2큐비트 게이트 이전 (왼쪽)에 적용된 것과 2큐비트 게이트 이후 (오른쪽)에 적용된 것이 상쇄되도록 선택됩니다. 이런 의미에서 두 큐비트 연산은 동일하지만 수행 방식이 다릅니다. 폴리 트월링의 한 가지 장점은 일관된 오류를 확률적 오류로 바꾸어 평균을 더 많이 내서 개선할 수 있다는 것입니다.
트랜스파일러 패스는 DAG에서 작동하므로 재정의해야 할 중요한 메서드는 DAG를 입력으로 받는 .run() 입니다. 그림과 같이 폴리스 쌍을 초기화하면 각 2쿼비트 게이트의 작동이 유지됩니다. 이는 도우미 메서드 build_twirl_set 를 사용하여 수행되며, 이 메서드는 각 2큐비트 폴리( pauli_basis(2) 에서 가져온 것)를 살펴보고 연산을 보존하는 다른 폴리를 찾습니다.
DAG에서 op_nodes() 메서드를 사용하여 모든 노드를 반환합니다. DAG는 큐비트에서 중단 없이 실행되는 노드의 시퀀스인 런을 수집하는 데에도 사용할 수 있습니다. 단일 큐비트 실행은 collect_1q_runs, 2큐비트 실행은 collect_2q_runs, 명령어 이름이 네임리스트에 있는 노드 실행은 collect_runs 로 수집할 수 있습니다. DAGCircuit 에는 그래프를 검색하고 탐색하는 다양한 방법이 있습니다. 일반적으로 사용되는 방법 중 하나는 종속성 순서대로 노드를 제공하는 topological_op_nodes 입니다. bfs_successors 같은 다른 메서드는 주로 노드가 DAG의 후속 작업과 상호 작용하는 방식을 결정하는 데 사용됩니다.
이 예제에서는 명령어를 나타내는 각 노드를 미니 DAG로 구축된 서브회로로 대체하고자 합니다. 미니 DAG에는 2쿼비트 양자 레지스터가 추가되었습니다. apply_operation_back 을 사용하여 미니 DAG에 연산을 추가하면 Instruction 이 미니 DAG의 출력에 배치됩니다(반면 apply_operation_front 은 미니 DAG의 입력에 배치됩니다). 그런 다음 노드는 substitute_node_with_dag 를 사용하여 미니 DAG로 대체되고, 이 프로세스는 DAG의 CXGate 및 ECRGate 의 각 인스턴스( IBM® 백엔드의 2쿼비트 기반 게이트에 해당)에 걸쳐 계속됩니다.
from qiskit.dagcircuit import DAGCircuit
from qiskit.circuit import QuantumCircuit, QuantumRegister, Gate
from qiskit.circuit.library import CXGate, ECRGate
from qiskit.transpiler import PassManager
from qiskit.transpiler.basepasses import TransformationPass
from qiskit.quantum_info import Operator, pauli_basis
import numpy as np
from typing import Iterable, Optionalclass PauliTwirl(TransformationPass):
"""Add Pauli twirls to two-qubit gates."""
def __init__(
self,
gates_to_twirl: Optional[Iterable[Gate]] = None,
):
"""
Args:
gates_to_twirl: Names of gates to twirl. The default behavior is to twirl all
two-qubit basis gates, `cx` and `ecr` for IBM backends.
"""
if gates_to_twirl is None:
gates_to_twirl = [CXGate(), ECRGate()]
self.gates_to_twirl = gates_to_twirl
self.build_twirl_set()
super().__init__()
def build_twirl_set(self):
"""
Build a set of Paulis to twirl for each gate and store internally as .twirl_set.
"""
self.twirl_set = {}
# iterate through gates to be twirled
for twirl_gate in self.gates_to_twirl:
twirl_list = []
# iterate through Paulis on left of gate to twirl
for pauli_left in pauli_basis(2):
# iterate through Paulis on right of gate to twirl
for pauli_right in pauli_basis(2):
# save pairs that produce identical operation as gate to twirl
if (Operator(pauli_left) @ Operator(twirl_gate)).equiv(
Operator(twirl_gate) @ pauli_right
):
twirl_list.append((pauli_left, pauli_right))
self.twirl_set[twirl_gate.name] = twirl_list
def run(
self,
dag: DAGCircuit,
) -> DAGCircuit:
# collect all nodes in DAG and proceed if it is to be twirled
twirling_gate_classes = tuple(
gate.base_class for gate in self.gates_to_twirl
)
for node in dag.op_nodes():
if not isinstance(node.op, twirling_gate_classes):
continue
# random integer to select Pauli twirl pair
pauli_index = np.random.randint(
0, len(self.twirl_set[node.op.name])
)
twirl_pair = self.twirl_set[node.op.name][pauli_index]
# instantiate mini_dag and attach quantum register
mini_dag = DAGCircuit()
register = QuantumRegister(2)
mini_dag.add_qreg(register)
# apply left Pauli, gate to twirl, and right Pauli to empty mini-DAG
mini_dag.apply_operation_back(
twirl_pair[0].to_instruction(), [register[0], register[1]]
)
mini_dag.apply_operation_back(node.op, [register[0], register[1]])
mini_dag.apply_operation_back(
twirl_pair[1].to_instruction(), [register[0], register[1]]
)
# substitute gate to twirl node with twirling mini-DAG
dag.substitute_node_with_dag(node, mini_dag)
return dag트랜스파일러 PauliTwirl 패스를 사용하십시오
다음 코드는 위에서 생성한 패스를 사용하여 회로를 트랜스파일합니다. 단순 회로에 cx 및 ecr 게이트가 있다고 가정하자.
qc = QuantumCircuit(3)
qc.cx(0, 1)
qc.ecr(1, 2)
qc.ecr(1, 0)
qc.cx(2, 1)
qc.draw("mpl")Output:
사용자 지정 패스를 적용하려면 PauliTwirl 패스를 사용하여 패스 관리자를 빌드하고 50개 회로에서 실행합니다.
pm = PassManager([PauliTwirl()])
twirled_qcs = [pm.run(qc) for _ in range(50)]이제 각 2큐비트 게이트는 두 개의 폴리 사이에 끼어 있습니다.
twirled_qcs[-1].draw("mpl")Output:
qiskit.quantum_info 에서 Operator 를 사용하는 경우 연산자는 동일합니다:
np.all([Operator(twirled_qc).equiv(qc) for twirled_qc in twirled_qcs])Output:
np.True_
다음 단계
- 직접 패스를 작성하는 대신
generate_preset_passmanager함수를 사용하는 방법을 알아보려면 번역 기본 설정 및 구성 옵션 항목부터 시작하세요. - Compare 트랜스파일러 설정 가이드를 시도해 보세요.
- 트랜스파일러 API 문서를 검토하십시오.