カスタム・トランスパイラー・パスを書く
このページのコードは、以下の要件に基づいて開発された。 これらのバージョンまたは新しいバージョンの使用をお勧めします。
qiskit[all]~=2.5.1
Qiskit SDKでは、カスタムトランスピレーションパスを作成し、 PassManager オブジェクト内で実行したり、 StagedPassManager に追加したりすることができます。 ここでは、量子回路のノイズの多い量子ゲートに対してパウリ・ツワーリングを実行するパスの作成に焦点を当て、トランスパイラ・パスの書き方を示します。 この例ではDAGを使用している。DAGは TransformationPass 型のパスで操作されるオブジェクトである。
パスを構築する前に、Qiskitの量子回路の内部表現である有向無サイクルグラフ(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')
回路 この回路のDAGを表示するには、
qiskit.tools.visualization.dag_drawer()。 グラフのノードには3種類ある:量子ビット/軌道ノード(緑)、演算ノード(青)、出力ノード(赤)。 各エッジは、2つのノード間のデータの流れ(または依存関係)を示す。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と連携して動作します。 分析パスは、DAGとその property_set.の両方で機能します。 彼らはDAGを変更することはできませんが、.を変更することはできます property_set。 これに対し、トランスフォーメーション・パスはDAGを変更するものであり、DAGを読み取ることはできるが(書き込みはできない) property_set。 例えば、変換パスでは回路をそのISA に変換したり、ルーティングパスを実行して必要な場所にSWAPゲートを挿入したりします。
トランスパイラパス PauliTwirl を作成する
以下の例では、パウリ・ツワールを追加するトランスパイラー・パスを構築している。 パウリ・ツワーリングは、量子ビットがどのようにノイズの多いチャネルを経験するかをランダムにするエラー抑制戦略であり、この例では2量子ビットゲートを想定している(1量子ビットゲートよりもはるかにエラーが発生しやすいため)。 パウリの回転は2量子ビットのゲートの動作には影響しない。 それらは、2量子ビットゲートの前 (左側)に適用されたものが、2量子ビットゲートの後 (右側)に適用されたものによって打ち消されるように選ばれる。 この意味で、2量子ビットの演算は同じだが、その方法は異なる。 パウリ・ツワーリングの利点のひとつは、コヒーレント誤差を確率的誤差に変えることで、より平均化することで改善できることだ。
Transpilerは DAGに作用するので、オーバーライドする重要なメソッドは .run()、DAGを入力として受け取る。 このようにポーリスのペアを初期化することで、各2量子ビットゲートの動作が保持される。 これはヘルパーメソッド build_twirl_set を使って行われる。ヘルパーメソッドは、( pauli_basis(2) から得られるような)各2量子ビットパウリを調べ、演算を保持するもう1つのパウリを見つける。
DAG から、 op_nodes() メソッドを使用して、そのすべてのノードを返す。 DAGは、量子ビット上で途切れることなく実行されるノードのシーケンスであるランを収集するためにも使用できる。 これらは、 collect_1q_runs で1量子ビットラン、 collect_2q_runs で2量子ビットラン、 collect_runs で命令名がネームリストにあるノードのランとして収集できる。 DAGCircuit には、グラフを検索したり走査したりするための多くのメソッドがある。 よく使われる方法の1つは、 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 を使用する
以下のコードは、上記で作成したパスを使用して回路をトランスパイルします。 と ecr``cx ゲートからなる単純な回路を考えよ。
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量子ビットのゲートは現在、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関数を使う方法を学ぶには、 Transpilation のデフォルト設定と構成オプションのトピックから始めてください。 - トランスパイラ設定の比較ガイドをお試しください。
- トランスパイラ API ドキュメントを確認してください。