{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "83596f71-5e63-4aa2-907b-75de8813d85a",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"動的回路を実行する\"\n",
        "description: \"IBM Quantum のCompute Serviceを使用して、従来のフィードフォワードおよび制御フロー（別名：動的回路）を実現します\"\n",
        "---\n",
        "\n",
        "<span id=\"execute-dynamic-circuits\" />\n",
        "\n",
        "# 動的回路を実行する\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2228a8a2-02b7-4a0b-bbe8-0c2933fbe44a",
      "metadata": {},
      "source": [
        "動的回路は、量子回路の実行途中で量子ビットを測定し、その測定結果に基づいて回路内で古典的な論理演算を実行できる強力なツールです。  このプロセスは、 *古典*的フィードフォワードとも呼ばれる。 ダイナミック回路を最大限に活用する方法についてはまだ研究の初期段階にあるものの、量子研究コミュニティではすでに、以下のような数多くの活用事例が特定されています：\n",
        "\n",
        "* [GHZ状態](https://journals.aps.org/prxquantum/abstract/10.1103/PRXQuantum.5.030339)[やW状態](https://arxiv.org/abs/2403.07604) （W状態の詳細については、 [「フィードフォワードを用いた浅い回路による状態準備」](https://arxiv.org/abs/2307.14840) も参照）、および広範な[行列積状態](https://arxiv.org/abs/2404.16083)など、効率的な量子状態の準備\n",
        "* 浅い回路を用いた、同一チップ上の量子ビット間における[効率的な長距離エンタングルメント](https://journals.aps.org/prxquantum/abstract/10.1103/PRXQuantum.5.030339)\n",
        "* [IQP型回路の](https://arxiv.org/pdf/2505.04705)効率的なサンプリング\n",
        "\n",
        "しかし、ダイナミック回路によってもたらされるこうした改善には、トレードオフが伴います。 回路途中での測定や古典的な演算は、通常、2量子ビットゲートよりも実行時間が長くなる傾向があり、この時間の増加によって、回路の深さを減らすことによるメリットが相殺されてしまう可能性がある。 したがって、 IBM Quantum®[ 新しいバージョン](/docs/guides/changelog-quantum-compute-service#new-version-dynamic-circuits)の動的回路をリリースするにあたり、回路中間測定の長さを短縮することは、改善の重点分野となる。  動的回路を使用する際のその他の制限事項については、「 [Estimator](/docs/guides/estimator-options#options-compatibility-table)」 または「 [Sampler](/docs/guides/sampler-options#options-compatibility-table)」 機能の互換性表を参照してください。\n",
        "\n",
        "[OpenQASM 3の仕様](https://openqasm.com/language/classical.html#looping-and-branching)では、いくつかの制御フロー構造が定義されていますが、 IBM Quantum Compute Serviceでは現在、条件分岐 `if` 文のみがサポートされています。 Qiskit SDK では、これは [QuantumCircuit](/docs/api/qiskit/qiskit.circuit.QuantumCircuit) の [if\\_test](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#if_test) メソッドに相当します。 このメソッドは[コンテキストマネージャー](https://docs.python.org/3/reference/datamodel.html#with-statement-context-managers) を返し、通常は ステートメント `with` 内で使用されます。 このガイドでは、この条件文の使用方法について説明します。\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  このガイドのコード例では、回路の途中での測定に標準的な測定命令を使用しています。 ただし、バックエンドが対応している場合は、代わりに の `MidCircuitMeasure` 指示を使用することをお勧めします。 詳細については[、「回路中間測定」のセクション](#midcircuit)を参照してください。\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7e9dc06d-85fa-4425-9bd1-ce5085be9741",
      "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",
        "    qiskit-ibm-runtime~=0.47.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c4616d43-f296-4a84-a79c-deb37fcdac15",
      "metadata": {},
      "source": [
        "<span id=\"find-backends-that-support-dynamic-circuits\" />\n",
        "\n",
        "## 動的回路をサポートするバックエンドを検索する\n",
        "\n",
        "自分のアカウントからアクセス可能で、動的サーキットをサポートしているすべてのバックエンドを確認するには、次のようなコードを実行してください。  この例では、 [ログイン情報が保存](/docs/guides/save-credentials)されていることを前提としています。  また、 IBM Quantum Compute Service アカウントを初期化する際に、 [認証情報を明示的に指定](/docs/guides/initialize-account#explicit)することも可能です。  これにより、例えば、特定のインスタンスやプランタイプで利用可能なバックエンドを確認できるようになります。\n",
        "\n",
        "<Admonition type=\"note\" title=\"ノート\">\n",
        "  * そのアカウントで利用可能なバックエンドは、認証情報で指定されたインスタンスによって異なります。\n",
        "  * ダイナミック回路の新バージョンが、すべてのバックエンドにおいて全ユーザー向けに利用可能になりました。 詳細については、 [お知らせ](/docs/guides/changelog-quantum-compute-service#new-dynamic-circuits)をご覧ください。\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "a63f07b1-9e8a-4086-ab01-552bd444dc9b",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[<IBMBackend('ibm_pittsburgh')>, <IBMBackend('ibm_boston')>, <IBMBackend('ibm_fez')>, <IBMBackend('ibm_marrakesh')>, <IBMBackend('ibm_kingston')>]\n"
          ]
        }
      ],
      "source": [
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "dc_backends = service.backends(dynamic_circuits=True)\n",
        "print(dc_backends)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1dca7d79-99ea-42bd-86f7-182266907a85",
      "metadata": {},
      "source": [
        "<span id=\"midcircuit\" />\n",
        "\n",
        "<span id=\"mid-circuit-measurements\" />\n",
        "\n",
        "## 回路の途中での測定\n",
        "\n",
        "v0.43.0 `qiskit-ibm-runtime` が登場する前は、 `measure` これが Qiskit における唯一の測定命令でした。 しかし、回路中間での測定は、 *端子*測定（回路の末端で行われる測定）とは異なる調整要件があります。 例えば、回路の測定を調整する際には、命令の実行時間を考慮する必要があります。なぜなら、命令が長くなると回路のノイズが増加するからです。 末端測定の後は命令がないため、末端測定における命令の実行時間は考慮する必要はありません。\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  この `MidCircuitMeasure` 命令は、バックエンドの `supported_instructions`. に報告された命令 `measure_2` に対応します。 ただし、すべてのバックエンド `measure_2` でサポートされているわけではありません。 を使用して `service.backends(filters=lambda b: \"measure_2\" in b.supported_instructions)` 、それをサポートしているバックエンドを検索してください。  今後、新たな測定項目が追加される可能性がありますが、その保証はありません。\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"midcircuitmeasure-method\" />\n",
        "\n",
        "### `MidCircuitMeasure`メソッド\n",
        "\n",
        "v0.43.0 `qiskit-ibm-runtime` において、この `MidCircuitMeasure` 命令が導入されました。 その名の通り、これは IBM® のQPUにおいて、回路の途中での実行に最適化された新しい測定命令です。  回路の途中での測定には `QuantumCircuit.measure` を使用することもできますが、その設計上、通常は `MidCircuitMeasure` の方が適しています。  例えば、これを使用する場合 `QuantumCircuit.measure`、回路にかかるオーバーヘッドは、…を使用する場合よりも少なくなります。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "87dfb9c7-1dc2-4752-bdc1-17b9144369f4",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "     ┌───┐┌────────────┐\n",
            "q_0: ┤ X ├┤0           ├\n",
            "     └───┘│            │\n",
            "q_1: ─────┤  Measure_2 ├\n",
            "          │            │\n",
            "c_0: ═════╡0           ╞\n",
            "          └────────────┘\n",
            "c_1: ═══════════════════\n",
            "                        \n"
          ]
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "from qiskit_ibm_runtime.circuit import MidCircuitMeasure\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(\n",
        "    operational=True, simulator=False, dynamic_circuits=True\n",
        ")\n",
        "\n",
        "circ = QuantumCircuit(2, 2)\n",
        "circ.x(0)\n",
        "circ.append(MidCircuitMeasure(), [0], [0])\n",
        "# circ.measure([0], [0])\n",
        "# circ.measure_all()\n",
        "print(circ.draw(cregbundle=False))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2b603f88-2e0e-4819-8342-8e3662949ff3",
      "metadata": {},
      "source": [
        "<Admonition type=\"attention\" title=\"重要な注意\">\n",
        "  * 測定機能を使用するには、少なくとも1つのクラシック・レジスタが必要です。\n",
        "  * 「Sampler」プリミティブでは、回路の測定が必要です。 「Estimator」プリミティブを使用して回路の測定値を追加することはできますが、それらは無視されます。\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9401a5cc-49e0-48b6-8deb-88e9b7da5a5a",
      "metadata": {},
      "source": [
        "<span id=\"store\" />\n",
        "\n",
        "## `Store`\n",
        "\n",
        "0.47.0 以降のバージョンでは `qiskit-ibm-runtime` 、ある式を繰り返し使用する場合は、\\`\\` [`store`](/docs/api/qiskit/circuit#store) 命令を使用してその式の計算結果を保存することができます。 処理は自動的に並列化されるため、実行時のコードの効率が大幅に向上します。\n",
        "\n",
        "詳細については、「 [古典的なフィードフォワードおよび制御フロー](/docs/guides/classical-feedforward-and-control-flow#store) ガイド」を参照してください。\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  実バックエンド上で を使用して `store` 古典的なレジスタに値を保存する場合、その値は実行中にメモリに保存されるだけであり、ジョブ結果にはコピーされたり返されたりすることはありません。\n",
        "\n",
        "  たとえば、次のコードでは、 `temp` 実行時に と `creg` の値は同じになり、 は `if_test` 期待どおりに動作します。 `creg`しかし、ジョブが終了した後、ジョブ結果として返される BitArray には `temp` 、の値**が含ま**れていません。  `0`つまり、 は `job.result()[0].data.temp` である。\n",
        "\n",
        "  ```python\n",
        "  creg = ClassicalRegister(3, \"c\")\n",
        "  temp = ClassicalRegister(3, \"temp\")\n",
        "  ...\n",
        "  qc.store(temp, creg)\n",
        "  with circuit.if_test((temp, 0b001)):\n",
        "      ...\n",
        "  ```\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3f374a74-c331-40de-8594-686e471058a2",
      "metadata": {},
      "source": [
        "<span id=\"full-example\" />\n",
        "\n",
        "## 完全な例\n",
        "\n",
        "次のコードは、 IBM® ハードウェア上で動的回路を作成して実行します。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "a7a9c998-4031-432f-978b-83edc040798f",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>>  Job ID:    d9mq9qnurbec73e67acg (DONE)\n"
          ]
        }
      ],
      "source": [
        "from qiskit_ibm_runtime import SamplerV2, QiskitRuntimeService\n",
        "from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(\n",
        "    operational=True, simulator=False, dynamic_circuits=True\n",
        ")\n",
        "\n",
        "# Create a dynamic circuit\n",
        "\n",
        "qubits = QuantumRegister(1)\n",
        "clbits = ClassicalRegister(1)\n",
        "qc = QuantumCircuit(qubits, clbits)\n",
        "(q0,) = qubits\n",
        "(c0,) = clbits\n",
        "\n",
        "qc.h(q0)\n",
        "qc.measure(q0, c0)\n",
        "with qc.if_test((c0, 1)):\n",
        "    qc.x(q0)\n",
        "qc.measure(q0, c0)\n",
        "\n",
        "\n",
        "# Convert to an ISA circuit for the given backend\n",
        "\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "isa_circuit = pm.run(qc)\n",
        "\n",
        "# Generate samplers for backend targets\n",
        "sampler = SamplerV2(backend)\n",
        "\n",
        "# Submit jobs\n",
        "sampler_job = sampler.run([isa_circuit])\n",
        "result = sampler_job.result()\n",
        "\n",
        "print(\n",
        "    f\">>> {' Job ID:':<10}  {sampler_job.job_id()} ({sampler_job.status()})\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c5b14dcf-edf4-4fef-bb49-e6b86f06afb0",
      "metadata": {},
      "source": [
        "<span id=\"quantum-compute-limitations\" />\n",
        "\n",
        "## 量子コンピューティングの限界\n",
        "\n",
        "Quantum Compute で動的回路を実行する際は、以下の制約事項に注意してください。\n",
        "\n",
        "* 制御電子機器の物理メモリ容量には限りがあるため、命令 `if` の数やオペランドのサイズにも制限があります。 この制限は、ジョブ（回路ではない）におけるブロードキャストの数およびブロードキャストされるビット数に依存します。\n",
        "\n",
        "  ある `if` 条件を処理する際には、その評価を行うために、測定データを制御ロジックに転送する必要があります。 ブロードキャストとは、固有の古典的データの転送であり、ブロードキャストされるビット数とは、転送される古典的ビットの数を指す。 以下の事項について検討します。\n",
        "\n",
        "  ```python\n",
        "  c0 = ClassicalRegister(3)\n",
        "  c1 = ClassicalRegister(5)\n",
        "  ...\n",
        "  with circuit.if_test((c0, 1)) ...\n",
        "  with circuit.if_test((c0, 3)) ...\n",
        "  with circuit.if_test((c1[2], 1)) ...\n",
        "  ```\n",
        "\n",
        "  前のコード例では、の `if_test` 最初の2つの `c0` オブジェクトは1つのブロードキャストと見なされます。これは、の内容が `c0` 変更されていないため、再ブロードキャストする必要がないからです。 この `if_test` 放送 `c1` は再放送です。 1つ目は3ビットすべてをブロードキャストし `c0` 、2つ目は1ビットのみをブロードキャストするため、合計で4ビットがブロードキャストされることになる。\n",
        "\n",
        "  現在、1回につき60ビットをブロードキャストする場合、このジョブでは約300回のブロードキャストが可能となります。 しかし、毎回1ビットずつ送信する場合、そのジョブでは2400回の送信が必要になります。\n",
        "\n",
        "* ` `if\\_test` statement` で使用されるオペランドは、32ビット以下でなければなりません。 したがって、全体を比較する場合、そのサイズは32 `ClassicalRegister``ClassicalRegister` ビット以下でなければなりません。 ただし、1つのビットだけを比較する場合、 `ClassicalRegister`そのビットはどのような `ClassicalRegister` 長さでも構いません（オペランドが1ビットのみであるため）。\n",
        "\n",
        "  たとえば、「Not valid」というコードブロックは、が32ビットを超 `cr` えているため動作しません。  ただし、「Valid」のコードブロックに示されているように、1ビットのみをテストする場合は、32ビットより広い古典的なレジスタを使用することも可能です。\n",
        "\n",
        "  <Tabs>\n",
        "    <TabItem value=\"Not valid\" label=\"Not valid\">\n",
        "      ```python\n",
        "         cr = ClassicalRegister(50)\n",
        "         qr = QuantumRegister(50)\n",
        "         circuit = QuantumCircuit(qr, cr)\n",
        "         ...\n",
        "         circ.measure(qr, cr)\n",
        "         with circ.if_test((cr, 15)):\n",
        "            ...\n",
        "      ```\n",
        "    </TabItem>\n",
        "\n",
        "    <TabItem value=\"Valid\" label=\"Valid\">\n",
        "      ```python\n",
        "         cr = ClassicalRegister(50)\n",
        "         qr = QuantumRegister(50)\n",
        "         circuit = QuantumCircuit(qr, cr)\n",
        "         ...\n",
        "         circ.measure(qr, cr)\n",
        "         with circ.if_test((cr[5], 1)):\n",
        "            ...\n",
        "      ```\n",
        "    </TabItem>\n",
        "  </Tabs>\n",
        "\n",
        "* 入れ子になった条件文は使用できません。 たとえば、次のコードブロックは、`が別の` `if_test` の中に含ま `if_test`れているため、動作しません：\n",
        "\n",
        "  <Tabs>\n",
        "    <TabItem value=\"Not valid\" label=\"Not valid\">\n",
        "      ```python\n",
        "         c1 = ClassicalRegister(1, \"c1\")\n",
        "         c2 = ClassicalRegister(2, \"c2\")\n",
        "         ...\n",
        "         with circ.if_test((c1, 1)):\n",
        "          with circ.if_test(c2, 1)):\n",
        "           ...\n",
        "      ```\n",
        "    </TabItem>\n",
        "\n",
        "    <TabItem value=\"Valid\" label=\"Valid\">\n",
        "      ```python\n",
        "      cr = ClassicalRegister(2)\n",
        "      ...\n",
        "      with circuit.if_test((cr, 0b11)):\n",
        "        ...\n",
        "      ```\n",
        "    </TabItem>\n",
        "  </Tabs>\n",
        "\n",
        "* 条件文内に `or` や `measurements `reset` ` を含めることはサポートされていません。\n",
        "\n",
        "* 算術演算はサポートされていません。\n",
        "\n",
        "* 「 [OpenQASM 3」の機能一覧表](/docs/guides/qasm-feature-table)を参照し、QiskitおよびQuantum Computeでどの OpenQASM 3機能がサポートされているかを確認してください。\n",
        "\n",
        "* IBM Quantum プリミティブに回路を渡す際の入力形式として OpenQASM 3（他の形式ではなく `QuantumCircuit`）を使用する場合、Qiskitに読み込める命令のみがサポートされます。 たとえば、従来の演算は、Qiskit に読み込むことができないため、サポートされていません。 詳細については、「 [OpenQASM 3のプログラムをQiskitにインポートする](/docs/guides/interoperate-qiskit-qasm3#import-an-openqasm-3-program-into-qiskit)」 を参照してください。\n",
        "\n",
        "* , `while`, および `switch` `for`コマンドはサポートされていません。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ca6e0493-d364-40bf-9f47-2e3feed9f82c",
      "metadata": {},
      "source": [
        "<span id=\"use-dynamic-circuits-with-estimator\" />\n",
        "\n",
        "## Estimator で動的回路を使用する\n",
        "\n",
        "Estimatorは動的回路に対応していないため、代わりに [Sampler](/docs/guides/get-started-with-sampler) を使用して、独自の測定回路を構築することができます。\n",
        "\n",
        "Estimatorの動作を再現するには、以下の手順に従ってください：\n",
        "\n",
        "1. すべての観測可能変数の項を1つのパーティションにまとめる。  例えば、 [API `PauliList`](/docs/api/qiskit/qiskit.quantum_info.PauliList#group_qubit_wise_commuting) を使用することで実現できます。\n",
        "   <Admonition type=\"note\">\n",
        "     [`BitArray`](/docs/en/api/qiskit/qiskit.primitives.BitArray#expectation_values) primitive 属性を使用すると、指定された観測量の期待値を計算できます。\n",
        "   </Admonition>\n",
        "2. パーティションごとに1つの基底変換回路を実行する（各パーティションに対して必要な基底変換を行う）。 詳細については、「Measurement bases [`measurement_bases` モジュール](https://qiskit.github.io/qiskit-addon-utils/apidocs/qiskit_addon_utils.exp_vals.html#qiskit_addon_utils.exp_vals.get_measurement_bases) 」アドオンユーティリティを参照してください。 詳細については、Qiskit addon utilities パッケージの[ドキュメント](https://qiskit.github.io/qiskit-addon-utils/)を参照してください。\n",
        "3. 各パーティションの結果を足し合わせます。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "07045397-6db8-4151-a1e4-de24a8f39ab6",
      "metadata": {},
      "source": [
        "<span id=\"restrictions\" />\n",
        "\n",
        "## 制約事項\n",
        "\n",
        "動的回路を使用する際の制限事項を確認するには[、機能互換性表](/docs/guides/estimator-options#options-compatibility-table)を参照してください。 なお、機能の互換性はプリミティブに依存しないことに注意してください。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6688e2e3-766b-4194-99db-ae097e9b8bc7",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## 次のステップ\n",
        "\n",
        "<Admonition type=\"tip\" title=\"推奨事項\">\n",
        "  * [stretch](/docs/guides/stretch) を使用して、正確な動的デカップリングを実装する方法について学びましょう。\n",
        "  * [従来のフィードフォワードおよび制御フロー](/docs/guides/classical-feedforward-and-control-flow) のガイドを確認してください。\n",
        "  * [回路スケジュールの可視化機能](/docs/guides/qiskit-runtime-circuit-timing)を活用して、動的回路のデバッグと最適化を行ってください。\n",
        "  * すべての関数が動的回路と互換性があるわけではありません。 詳細については、「 [Sampler](/docs/guides/sampler-options#feature-compatibility)」 の機能互換性に関するセクションをご確認ください。\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": 4
}