{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "4cb32582",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"トランスパイラパスにおけるDAGの操作\"\n",
        "description: \"ダイレクトド・アサイクリック・グラフ（DAG）を用いたQiskitトランスパイラ処理における量子回路の解析と変換手法\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore subdag DAGOpNode qargs cargs dag_drawer couplinglist */}\n",
        "\n",
        "<span id=\"work-with-dags-in-transpiler-passes\" />\n",
        "\n",
        "# トランスパイラパスにおけるDAGの操作\n",
        "\n",
        "Qiskitでは、トランスパイルステージにおいて、回路はDAGを用いて表現される。 一般にDAGは、頂点（「ノード」とも呼ばれる）と、頂点同士を特定の向きで結ぶ有向辺で構成される。 この表現は、個々の `DagNode` オブジェクトで構成される `qiskit.dagcircuit.DAGCircuit` オブジェクトを使って保存される。 ゲートの純粋なリスト（つまりネットリスト）よりもこの表現の利点は、演算間の情報の流れが明示的であるため、変換の決定が容易になることである。\n",
        "\n",
        "このガイドでは、DAGを使用してカスタム・トランスパイラ・パスを作成する方法を説明します。 簡単な回路を構築し、そのDAG表現を調べることから始め、基本的なDAG操作について調べ、カスタム `BasicMapper` パスを実装する。\n",
        "\n",
        "<span id=\"build-a-circuit-and-examine-its-dag\" />\n",
        "\n",
        "## 回路を構築し、その有向非巡回グラフ（DAG）を調べる\n",
        "\n",
        "以下のコード・スニペットは、測定結果に応じてベル状態を準備し、 $R_Z$ 回転を適用する単純な回路を作成することで、DAGを説明している。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "version-info-cell",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "{/*\n",
        "  DO NOT EDIT THIS CELL!!!\n",
        "  This cell's content is generated automatically by a script. Anything you add\n",
        "  here will be removed next time the notebook is run. To add new content, create\n",
        "  a new cell before or after this one.\n",
        "  */}\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"パッケージ・バージョン\">\n",
        "    このページのコードは、以下の要件に基づいて開発された。\n",
        "    これらのバージョンまたは新しいバージョンの使用をお勧めします。\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.1\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "1d16892a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/DAG-representation/extracted-outputs/1d16892a-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit\n",
        "from qiskit.converters import circuit_to_dag\n",
        "from qiskit.visualization import circuit_drawer\n",
        "from qiskit.visualization.dag_visualization import dag_drawer\n",
        "\n",
        "# Create circuit\n",
        "q = QuantumRegister(3, \"q\")\n",
        "c = ClassicalRegister(3, \"c\")\n",
        "circ = QuantumCircuit(q, c)\n",
        "circ.h(q[0])\n",
        "circ.cx(q[0], q[1])\n",
        "circ.measure(q[0], c[0])\n",
        "\n",
        "# Qiskit 2.0 uses if_test instead of c_if\n",
        "with circ.if_test((c, 2)):\n",
        "    circ.rz(0.5, q[1])\n",
        "\n",
        "circuit_drawer(circ, output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5971b6ed",
      "metadata": {},
      "source": [
        "DAGでは、3種類のグラフノードがある：qubit/clbit入力ノード（緑）、演算ノード（青）、出力ノード（赤）。 各エッジは、2つのノード間のデータの流れ（または依存関係）を示す。 この回路のDAGを表示するには、 qiskit.tools.visualization.dag\\_drawer （）関数を使用します。 (これを実行するには [Graphvizライブラリを](https://graphviz.org/download/)インストールする）\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "e498faa3",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/DAG-representation/extracted-outputs/e498faa3-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Convert to DAG\n",
        "dag = circuit_to_dag(circ)\n",
        "dag_drawer(dag)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3b728136",
      "metadata": {},
      "source": [
        "<span id=\"basic-dag-operations\" />\n",
        "\n",
        "## 基本的なDAG操作\n",
        "\n",
        "以下のコード例は、ノードへのアクセス、演算の追加、部分回路の置換など、DAGの一般的な操作を示している。 これらのオペレーションは、トランスパイラー・パスを構築するための基礎となる。\n",
        "\n",
        "<span id=\"get-all-operation-nodes-in-the-dag\" />\n",
        "\n",
        "## DAG内のすべての操作ノードを取得する\n",
        "\n",
        "`op_nodes()` メソッドは、回路内の `DAGOpNode` オブジェクトの反復可能なリストを返す：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "4f848695",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[DAGOpNode(op=Instruction(name='h', num_qubits=1, num_clbits=0, params=[]), qargs=(<Qubit register=(3, \"q\"), index=0>,), cargs=()),\n",
              " DAGOpNode(op=Instruction(name='cx', num_qubits=2, num_clbits=0, params=[]), qargs=(<Qubit register=(3, \"q\"), index=0>, <Qubit register=(3, \"q\"), index=1>), cargs=()),\n",
              " DAGOpNode(op=Instruction(name='measure', num_qubits=1, num_clbits=1, params=[]), qargs=(<Qubit register=(3, \"q\"), index=0>,), cargs=(<Clbit register=(3, \"c\"), index=0>,)),\n",
              " DAGOpNode(op=Instruction(name='if_else', num_qubits=1, num_clbits=3, params=[<qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7fcbf0f00510>, None]), qargs=(<Qubit register=(3, \"q\"), index=1>,), cargs=(<Clbit register=(3, \"c\"), index=0>, <Clbit register=(3, \"c\"), index=1>, <Clbit register=(3, \"c\"), index=2>))]"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "dag.op_nodes()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8f2676b9",
      "metadata": {},
      "source": [
        "各ノードは `DAGOpNode` クラスのインスタンスである：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "5866159f",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "node name: if_else\n",
            "op: Instruction(name='if_else', num_qubits=1, num_clbits=3, params=[<qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7fcbf0fefbd0>, None])\n",
            "qargs: (<Qubit register=(3, \"q\"), index=1>,)\n",
            "cargs: (<Clbit register=(3, \"c\"), index=0>, <Clbit register=(3, \"c\"), index=1>, <Clbit register=(3, \"c\"), index=2>)\n",
            "condition: (ClassicalRegister(3, 'c'), 2)\n"
          ]
        }
      ],
      "source": [
        "node = dag.op_nodes()[3]\n",
        "print(\"node name:\", node.name)\n",
        "print(\"op:\", node.op)\n",
        "print(\"qargs:\", node.qargs)\n",
        "print(\"cargs:\", node.cargs)\n",
        "print(\"condition:\", node.op.condition)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f2560cc1",
      "metadata": {},
      "source": [
        "<span id=\"add-an-operation-to-the-back\" />\n",
        "\n",
        "## 操作を後ろに追加する\n",
        "\n",
        "`apply_operation_back()` 、DAGCircuitの末尾に操作が追加される。 これは、回路内のすべての既存の操作の後に、指定された量子ビットに作用するように指定されたゲートを追加します。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "3c144b49",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/DAG-representation/extracted-outputs/3c144b49-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.circuit.library import HGate\n",
        "\n",
        "dag.apply_operation_back(HGate(), qargs=[q[0]])\n",
        "dag_drawer(dag)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "80af1d3d",
      "metadata": {},
      "source": [
        "<span id=\"add-an-operation-to-the-front\" />\n",
        "\n",
        "## 操作を前面に追加する\n",
        "\n",
        "`apply_operation_front()` 、DAGCircuitの先頭にオペレーションが追加される。 これは、指定されたゲートを回路内の既存のすべての演算の前に挿入し、事実上、最初に実行される演算にする。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "ed80a69f",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/DAG-representation/extracted-outputs/ed80a69f-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.circuit.library import CCXGate\n",
        "\n",
        "dag.apply_operation_front(CCXGate(), qargs=[q[0], q[1], q[2]])\n",
        "dag_drawer(dag)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4bcdf5fe",
      "metadata": {},
      "source": [
        "<span id=\"substitute-a-node-with-a-subcircuit\" />\n",
        "\n",
        "## ノードをサブ回路で置換する\n",
        "\n",
        "DAGCircuitの特定の操作を表すノードは、サブサーキットに置き換えられる。 まず、新しいサブDAGを所望のゲート・シーケンスで構築し、 `substitute_node_with_dag()`、回路の残りの部分との接続を維持したまま、ターゲット・ノードをこのサブDAGで置き換える。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "fdb3dd70",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/DAG-representation/extracted-outputs/fdb3dd70-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.dagcircuit import DAGCircuit\n",
        "from qiskit.circuit.library import CHGate, U2Gate, CXGate\n",
        "\n",
        "# Build sub-DAG\n",
        "mini_dag = DAGCircuit()\n",
        "p = QuantumRegister(2, \"p\")\n",
        "mini_dag.add_qreg(p)\n",
        "mini_dag.apply_operation_back(CHGate(), qargs=[p[1], p[0]])\n",
        "mini_dag.apply_operation_back(U2Gate(0.1, 0.2), qargs=[p[1]])\n",
        "\n",
        "# Replace CX with mini_dag\n",
        "cx_node = dag.op_nodes(op=CXGate).pop()\n",
        "dag.substitute_node_with_dag(cx_node, mini_dag, wires=[p[0], p[1]])\n",
        "dag_drawer(dag)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "028566f7",
      "metadata": {},
      "source": [
        "すべての変換が完了すると、DAGは通常の `QuantumCircuit` オブジェクトに戻すことができる。 これがトランスパイラ・パイプラインの動作である。 回路が取り込まれ、DAG形式で処理され、変換された回路が出力される。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "786571f7",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/DAG-representation/extracted-outputs/786571f7-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.converters import dag_to_circuit\n",
        "\n",
        "new_circ = dag_to_circuit(dag)\n",
        "circuit_drawer(new_circ, output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f743bb3b",
      "metadata": {},
      "source": [
        "<span id=\"implement-a-basicmapper-pass\" />\n",
        "\n",
        "## BasicMapper パスを実装する\n",
        "\n",
        "DAG構造は、トランスパイラー・パスの記述に活用できる。 以下の例では、量子ビットの接続性が制限されたデバイスに任意の回路をマッピングするために、 `BasicMapper` 。 その他のガイダンスについては、 [カスタム・トランスパイラー・パスの書き方に関する](/docs/guides/custom-transpiler-pass)ガイドを参照してください。\n",
        "\n",
        "パスは `TransformationPass` と定義され、回路を変更することを意味する。 これは、DAGをレイヤーごとに走査し、各命令がデバイスのカップリング・マップによって課された制約を満たしているかどうかをチェックすることによって行われる。 違反が検出された場合、スワップ・パスが決定され、それに応じて必要なスワップ・ゲートが挿入される。\n",
        "\n",
        "トランスパイラー・パスを作成する際、最初に決定することは、パスを `TransformationPass` と `AnalysisPass` のどちらから継承するかを選択することである。 変換パスは回路を修正するように設計されているのに対し、解析パスは後続のパスで使用するための情報を抽出することだけを目的としている。 主な機能は `run(dag)` 。 最後に、パスを `qiskit.transpiler.passes` モジュールに登録する。\n",
        "\n",
        "この特定のパスでは、DAGはレイヤーごとにトラバースされる（各レイヤーは、量子ビットの不連続なセットに作用する操作を含み、したがって独立して実行できる）。 各操作において、カップリングマップ制約が満たされない場合、適切なスワップパスが特定され、関係する量子ビットを隣接させるために必要なスワップが挿入される。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "8c0d7e5a",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler.basepasses import TransformationPass\n",
        "from qiskit.transpiler import Layout\n",
        "from qiskit.circuit.library import SwapGate\n",
        "\n",
        "\n",
        "class BasicSwap(TransformationPass):\n",
        "    def __init__(self, coupling_map, initial_layout=None):\n",
        "        super().__init__()\n",
        "        self.coupling_map = coupling_map\n",
        "        self.initial_layout = initial_layout\n",
        "\n",
        "    def run(self, dag):\n",
        "        new_dag = DAGCircuit()\n",
        "        for qreg in dag.qregs.values():\n",
        "            new_dag.add_qreg(qreg)\n",
        "        for creg in dag.cregs.values():\n",
        "            new_dag.add_creg(creg)\n",
        "\n",
        "        if self.initial_layout is None:\n",
        "            self.initial_layout = Layout.generate_trivial_layout(\n",
        "                *dag.qregs.values()\n",
        "            )\n",
        "\n",
        "        current_layout = self.initial_layout.copy()\n",
        "\n",
        "        for layer in dag.serial_layers():\n",
        "            subdag = layer[\"graph\"]\n",
        "            for gate in subdag.two_qubit_ops():\n",
        "                q0, q1 = gate.qargs\n",
        "                p0 = current_layout[q0]\n",
        "                p1 = current_layout[q1]\n",
        "\n",
        "                if self.coupling_map.distance(p0, p1) != 1:\n",
        "                    path = self.coupling_map.shortest_undirected_path(p0, p1)\n",
        "                    for i in range(len(path) - 2):\n",
        "                        wire1, wire2 = path[i], path[i + 1]\n",
        "                        qubit1 = current_layout[wire1]\n",
        "                        qubit2 = current_layout[wire2]\n",
        "                        new_dag.apply_operation_back(\n",
        "                            SwapGate(), qargs=[qubit1, qubit2]\n",
        "                        )\n",
        "                        current_layout.swap(wire1, wire2)\n",
        "\n",
        "            new_dag.compose(\n",
        "                subdag, qubits=current_layout.reorder_bits(new_dag.qubits)\n",
        "            )\n",
        "\n",
        "        return new_dag"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4a95eaab",
      "metadata": {},
      "source": [
        "これで、パスを小さな回路例でテストすることができる。 新しく定義されたパスを含むパス・マネージャーが構築される。 そして、例の回路がこのパス・マネージャーに提供され、変換された新しい回路が出力として得られる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "2f35375f",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/DAG-representation/extracted-outputs/2f35375f-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.transpiler import CouplingMap, PassManager\n",
        "from qiskit import QuantumRegister, QuantumCircuit\n",
        "\n",
        "q = QuantumRegister(7, \"q\")\n",
        "in_circ = QuantumCircuit(q)\n",
        "in_circ.h(q[0])\n",
        "in_circ.cx(q[0], q[4])\n",
        "in_circ.cx(q[2], q[3])\n",
        "in_circ.cx(q[6], q[1])\n",
        "in_circ.cx(q[5], q[0])\n",
        "in_circ.rz(0.1, q[2])\n",
        "in_circ.cx(q[5], q[0])\n",
        "\n",
        "coupling = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]\n",
        "coupling_map = CouplingMap(couplinglist=coupling)\n",
        "\n",
        "pm = PassManager()\n",
        "pm.append(BasicSwap(coupling_map))\n",
        "\n",
        "out_circ = pm.run(in_circ)\n",
        "\n",
        "in_circ.draw(output=\"mpl\")\n",
        "out_circ.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "56b80ce3",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## 次のステップ\n",
        "\n",
        "<Admonition type=\"tip\" title=\"推奨事項\">\n",
        "  * [カスタムトランスパイラ・パ](/docs/guides/custom-transpiler-pass)スの作成に関するガイドを確認してください\n",
        "  * [カスタムバックエンドの作成](/docs/guides/custom-backend)方法と、それに対するトランスパイルの方法について学ぶ\n",
        "  * [トランスパイラ設定の比較](/docs/guides/circuit-transpilation-settings)ガイドをお試しください。\n",
        "  * [DAG Circuit API](/docs/api/qiskit/dagcircuit) のドキュメントを確認してください。\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}