{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "828c3465-62a7-4c42-b376-e3ec32f67595",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"ノイズ学習ヘルパー\"\n",
        "description: \"qiskit-ibm-runtime でワークロードを実行した際に作成されたノイズモデルを保存するために、ノイズ学習ヘルパープログラムを使い始めましょう\"\n",
        "---\n",
        "\n",
        "<span id=\"noise-learning-helper\" />\n",
        "\n",
        "# ノイズ学習ヘルパー\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "40a246f5-4efd-4fb0-861b-c4e013c1572a",
      "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.4.1\n",
        "    qiskit-ibm-runtime~=0.47.0\n",
        "    samplomatic~=0.18.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cce93074-df51-4760-9fce-5a520c3bc59a",
      "metadata": {},
      "source": [
        "エラー軽減手法[であるPEA](/docs/guides/error-mitigation-and-suppression-techniques#pea)[ とPEC](/docs/guides/error-mitigation-and-suppression-techniques#pec) は、いずれも[パウリ・リンドブラッドノイズモデル](https://arxiv.org/abs/2201.09866)に基づくノイズ学習コンポーネントを利用しており、これは通常、1つ以上のジョブを介して `qiskit-ibm-runtime` 送信された後、実行中に管理されるものであり、適合されたノイズモデルへのローカルアクセスは一切行われない。 ただし、 v0.27.1 時点 `qiskit-ibm-runtime` では、これらのノイズ学習実験の結果を取得するために、および関連する [`NoiseLearnerOptions`](/docs/api/qiskit-ibm-runtime/options-noise-learner-options) クラ [`NoiseLearner`](/docs/api/qiskit-ibm-runtime/noise-learner) スが作成されています。 これらの結果は、ローカルにファイル `NoiseLearnerResult` として保存し、後の実験で入力データとして使用することができます。 このページでは、その使用方法と利用可能なオプションの概要を説明します。\n",
        "\n",
        "さらに、 v0.47.0 以降では `qiskit-ibm-runtime` 、Executor プリミティブと互換性のある新しい `NoiseLearnerV3` クラスが用意されています。 この新バージョン[もディレクテッド実行モデル](/docs/guides/directed-execution-model)の一部であり、学習対象とするレイヤーを明示的に指定できるようになります。\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  `NoiseLearner` EstimatorV2 でのみ動作し、 `NoiseLearnerV3` Executorでのみ動作します。\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"noiselearner\" />\n",
        "\n",
        "## `NoiseLearner`\n",
        "\n",
        "<span id=\"overview\" />\n",
        "\n",
        "### 概要\n",
        "\n",
        "この `NoiseLearner` 講義では、1つ（または複数）の回路について、パウリ・リンドブラッドのノイズモデルに基づいてノイズ過程を特徴づける実験を行います。 このクラスは、学習実験を実行するメソッド `run()` を備えており、回路のリストまたは [PUB](/docs/guides/primitive-input-output) を入力として受け取り、学習されたノイズチャネルと、送信されたジョブに関するメタデータを含むオブジェクト `NoiseLearnerResult` を返します。 以下は、ヘルパープログラムの使用方法を示すコードの抜粋です。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "d9a5320d-8ec6-483a-9ecf-931b0f5f5d13",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "from qiskit.transpiler import CouplingMap\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2\n",
        "from qiskit_ibm_runtime.noise_learner import NoiseLearner\n",
        "from qiskit_ibm_runtime.options import (\n",
        "    NoiseLearnerOptions,\n",
        "    ResilienceOptionsV2,\n",
        "    EstimatorOptions,\n",
        ")\n",
        "\n",
        "# Build a circuit with two entangling layers\n",
        "num_qubits = 27\n",
        "edges = list(CouplingMap.from_line(num_qubits, bidirectional=False))\n",
        "even_edges = edges[::2]\n",
        "odd_edges = edges[1::2]\n",
        "\n",
        "circuit = QuantumCircuit(num_qubits)\n",
        "for pair in even_edges:\n",
        "    circuit.cx(pair[0], pair[1])\n",
        "for pair in odd_edges:\n",
        "    circuit.cx(pair[0], pair[1])\n",
        "\n",
        "# Choose a backend to run on\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy()\n",
        "\n",
        "# Transpile the circuit for execution\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
        "circuit_to_learn = pm.run(circuit)\n",
        "\n",
        "# Instantiate a NoiseLearner object and execute the noise learning program\n",
        "learner = NoiseLearner(mode=backend)\n",
        "job = learner.run([circuit_to_learn])\n",
        "noise_model = job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ef141d65-d14d-4e2b-9813-b8766e29fdb9",
      "metadata": {},
      "source": [
        "その結果 `NoiseLearnerResult.data` 、ターゲット回路に属する個々のエンタングルメント層ごとの[ノイズモデル](https://arxiv.org/abs/2201.09866)を含むオブジェクトの [`LayerError`](/docs/api/qiskit-ibm-runtime/results-layer-error) リストが得られます。 それぞれ `LayerError` は、回路と一連の量子ビットラベルという形式でレイヤー情報を保存するとともに、そのレイヤーについて学習されたノイズモデルの情報 [`PauliLindbladError`](/docs/api/qiskit-ibm-runtime/results-pauli-lindblad-error) も併せて保存します。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a9be8ff1-7494-407c-853c-50d471a2f55f",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Noise learner result contains 2 entries and has the following type:\n",
            " <class 'qiskit_ibm_runtime.utils.noise_learner_result.NoiseLearnerResult'>\n",
            "\n",
            "Each element of `NoiseLearnerResult` then contains an object of type:\n",
            " <class 'qiskit_ibm_runtime.utils.noise_learner_result.LayerError'>\n",
            "\n",
            "And each of these `LayerError` objects possess data on the generators for the error channel: \n",
            "['IIIIIIIIIIIIIIIIIIIIIIIIIIX', 'IIIIIIIIIIIIIIIIIIIIIIIIIIY',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIIZ', 'IIIIIIIIIIIIIIIIIIIIIIIIIXI',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIXX', 'IIIIIIIIIIIIIIIIIIIIIIIIIXY',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIXZ', 'IIIIIIIIIIIIIIIIIIIIIIIIIYI',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIYX', 'IIIIIIIIIIIIIIIIIIIIIIIIIYY',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIYZ', 'IIIIIIIIIIIIIIIIIIIIIIIIIZI',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIZX', 'IIIIIIIIIIIIIIIIIIIIIIIIIZY',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIZZ', 'IIIIIIIIIIIIIIIIIIIIIIIIXII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIXIX', 'IIIIIIIIIIIIIIIIIIIIIIIIXIY',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIXIZ', 'IIIIIIIIIIIIIIIIIIIIIIIIYII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIYIX', 'IIIIIIIIIIIIIIIIIIIIIIIIYIY',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIYIZ', 'IIIIIIIIIIIIIIIIIIIIIIIIZII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIZIX', 'IIIIIIIIIIIIIIIIIIIIIIIIZIY',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIZIZ', 'IIIIIIIIIIIIIIIIIIIIIIIXIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIYIII', 'IIIIIIIIIIIIIIIIIIIIIIIZIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIXIIII', 'IIIIIIIIIIIIIIIIIIIIIIXXIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIXYIII', 'IIIIIIIIIIIIIIIIIIIIIIXZIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIYIIII', 'IIIIIIIIIIIIIIIIIIIIIIYXIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIYYIII', 'IIIIIIIIIIIIIIIIIIIIIIYZIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIZIIII', 'IIIIIIIIIIIIIIIIIIIIIIZXIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIZYIII', 'IIIIIIIIIIIIIIIIIIIIIIZZIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIXIIIII', 'IIIIIIIIIIIIIIIIIIIIIXXIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIXYIIII', 'IIIIIIIIIIIIIIIIIIIIIXZIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIYIIIII', 'IIIIIIIIIIIIIIIIIIIIIYXIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIYYIIII', 'IIIIIIIIIIIIIIIIIIIIIYZIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIZIIIII', 'IIIIIIIIIIIIIIIIIIIIIZXIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIZYIIII', 'IIIIIIIIIIIIIIIIIIIIIZZIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIXIIIIII', 'IIIIIIIIIIIIIIIIIIIIXXIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIXYIIIII', 'IIIIIIIIIIIIIIIIIIIIXZIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIYIIIIII', 'IIIIIIIIIIIIIIIIIIIIYXIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIYYIIIII', 'IIIIIIIIIIIIIIIIIIIIYZIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIZIIIIII', 'IIIIIIIIIIIIIIIIIIIIZXIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIZYIIIII', 'IIIIIIIIIIIIIIIIIIIIZZIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIXIIIIIII', 'IIIIIIIIIIIIIIIIIIIXXIIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIXYIIIIII', 'IIIIIIIIIIIIIIIIIIIXZIIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIYIIIIIII', 'IIIIIIIIIIIIIIIIIIIYXIIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIYYIIIIII', 'IIIIIIIIIIIIIIIIIIIYZIIIIII', ...]\n",
            "\n",
            "Along with the error rates: \n",
            "[5.9e-04 5.3e-04 5.7e-04 ... 0.0e+00 1.0e-05 0.0e+00]\n",
            "\n"
          ]
        }
      ],
      "source": [
        "import numpy\n",
        "\n",
        "print(\n",
        "    f\"Noise learner result contains {len(noise_model.data)} entries\"\n",
        "    f\" and has the following type:\\n {type(noise_model)}\\n\"\n",
        ")\n",
        "print(\n",
        "    f\"Each element of `NoiseLearnerResult` then contains\"\n",
        "    f\" an object of type:\\n {type(noise_model.data[0])}\\n\"\n",
        ")\n",
        "# Results are truncated\n",
        "with numpy.printoptions(threshold=200):\n",
        "    print(\n",
        "        f\"And each of these `LayerError` objects possess\"\n",
        "        f\" data on the generators for the error channel: \\n\"\n",
        "        f\"{noise_model.data[0].error.generators}\\n\"\n",
        "    )\n",
        "# Results are truncated\n",
        "with numpy.printoptions(threshold=200):\n",
        "    print(\n",
        "        f\"Along with the error rates: \\n{noise_model.data[0].error.rates}\\n\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "faa3892e-30a5-48f7-87dd-39ab1b0846d9",
      "metadata": {},
      "source": [
        "ノイズ学習結果の `LayerError.error` 属性には、適合したパウリ・リンドブラッド・モデルの発電機とエラー・レートが含まれており、次のような形になっている\n",
        "\n",
        "$\\Lambda(\\rho) = \\exp{\\sum_j r_j \\left(P_j \\rho P_j^\\dagger - \\rho\\right)},$\n",
        "\n",
        "ここで、 $r_j$ は `LayerError.rates` で、 $P_j$ は `LayerError.generators` で指定されているパウリ演算子である。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fc0000e6-e77a-4b87-a9ee-262f904953fc",
      "metadata": {},
      "source": [
        "<span id=\"noise-learning-options\" />\n",
        "\n",
        "### ノイズ学習オプション\n",
        "\n",
        "オブジェクトを `NoiseLearner` インスタンス化する際、いくつかの入力オプションから選択できます。 これらのオプションは クラス `qiskit_ibm_runtime.options.NoiseLearnerOptions` によってカプセル化されており、学習するレイヤーの最大数、ランダム化の回数、ツイリング戦略などを指定する機能が含まれています。 [`NoiseLearnerOptions`](/docs/api/qiskit-ibm-runtime/options-noise-learner-options) 詳細については、APIドキュメントを参照してください。\n",
        "\n",
        "`NoiseLearnerOptions` 以下は、実験 `NoiseLearner` で を使用する方法を示す簡単な例です：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "fcd1bd93-405d-4cfb-a5d1-bb646404aa58",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Build a GHZ circuit\n",
        "circuit = QuantumCircuit(10)\n",
        "circuit.h(0)\n",
        "circuit.cx(range(0, 9), range(1, 10))\n",
        "# Choose a backend to run on\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy()\n",
        "\n",
        "# Transpile the circuit for execution\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
        "circuit_to_run = pm.run(circuit_to_learn)\n",
        "\n",
        "# Instantiate a NoiseLearnerOptions object\n",
        "learner_options = NoiseLearnerOptions(\n",
        "    max_layers_to_learn=3, num_randomizations=32, twirling_strategy=\"all\"\n",
        ")\n",
        "\n",
        "# Instantiate a NoiseLearner object and execute the noise learning program\n",
        "learner = NoiseLearner(mode=backend, options=learner_options)\n",
        "job = learner.run([circuit_to_run])\n",
        "noise_model = job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d952d0cc-497b-45ae-a55e-2b611ebbe4a3",
      "metadata": {},
      "source": [
        "<span id=\"input-noise-model-to-a-primitive\" />\n",
        "\n",
        "### 原始体にノイズモデルを入力する\n",
        "\n",
        "回路で学習されたノイズモデルは、 IBM Quantum`EstimatorV2` プリミティブへの入力としても使用できます。 これは、いくつかの異なる方法でプリミティブに渡すことができます。 次の 3 つの例では、Estimator プリミティブをインスタンス化する前に オブジェクト `ResilienceOptionsV2` を使用する方法や、適切な形式の辞書を渡す方法など、ノイズモデルを 属性 `estimator.options` に直接渡す方法を示しています。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "9826013a-f9fd-4d72-baa7-dc5395b81007",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Pass the noise model to the `estimator.options` attribute directly\n",
        "estimator = EstimatorV2(mode=backend)\n",
        "estimator.options.resilience.layer_noise_model = noise_model"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "7ab10595-5c20-4954-9001-70b8879926b4",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Specify options through a ResilienceOptionsV2 object\n",
        "resilience_options = ResilienceOptionsV2(layer_noise_model=noise_model)\n",
        "estimator_options = EstimatorOptions(resilience=resilience_options)\n",
        "estimator = EstimatorV2(mode=backend, options=estimator_options)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "17b1f8de-fe14-4998-898b-ecd409a5efd3",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Specify options by using a dictionary\n",
        "options_dict = {\n",
        "    \"resilience_level\": 2,\n",
        "    \"resilience\": {\"layer_noise_model\": noise_model},\n",
        "}\n",
        "\n",
        "estimator = EstimatorV2(mode=backend, options=options_dict)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8c167b65-2e9a-41b9-b593-edfe80a2fde4",
      "metadata": {},
      "source": [
        "ノイズモデルがオブジェクト `EstimatorV2` に渡されると、通常通りワークロードを実行し、エラーの緩和を行うことができます。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dad71939-7fe2-42f0-90fe-6974fe0854e7",
      "metadata": {},
      "source": [
        "<span id=\"noiselearnerv3\" />\n",
        "\n",
        "## NoiseLearnerV3\n",
        "\n",
        "<span id=\"overview\" />\n",
        "\n",
        "### 概要\n",
        "\n",
        "`NoiseLearner`と同様に、この `NoiseLearnerV3` クラスは、1つまたは複数の回路について、パウリ・リンドブラッドのノイズモデルに基づいてノイズ過程を特徴づける実験を行う。 その `run()` メソッドは命令のリストを受け取ります。各命令は、 [ISA](/docs/guides/transpile#instruction-set-architecture) 演算を含むtwirled-annotated [`BoxOp`](/docs/api/qiskit/qiskit.circuit.BoxOp) でなければなりません。\n",
        "\n",
        "`NoiseLearnerV3` ジョブの結果には、入力された各命令に対応するオブジェクトが1つずつ含まれた [`NoiseLearnerV3Result`](/docs/api/qiskit-ibm-runtime/results-noise-learner-v3-result) リストが含まれます。\n",
        "以下のコードは、ヘルパープログラムの使用方法を示しています。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "0bbd2c21-6045-4954-aee9-339e6b060805",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Found 3 unique layers\n",
            "Each instruction is of type <class 'qiskit.circuit.controlflow.box.BoxOp'>\n",
            "And has annotations: [Twirl(group='pauli', dressing='left', decomposition='rzsx'), InjectNoise(ref='r789B', modifier_ref='', site='before')]\n"
          ]
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "from qiskit.transpiler import CouplingMap\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService, Executor\n",
        "from qiskit_ibm_runtime.noise_learner_v3 import NoiseLearnerV3\n",
        "from samplomatic.transpiler import generate_boxing_pass_manager\n",
        "from samplomatic.utils import find_unique_box_instructions\n",
        "\n",
        "\n",
        "# Build a circuit with two entangling layers\n",
        "num_qubits = 27\n",
        "edges = list(CouplingMap.from_line(num_qubits, bidirectional=False))\n",
        "even_edges = edges[::2]\n",
        "odd_edges = edges[1::2]\n",
        "\n",
        "circuit = QuantumCircuit(num_qubits)\n",
        "for pair in even_edges:\n",
        "    circuit.cx(pair[0], pair[1])\n",
        "for pair in odd_edges:\n",
        "    circuit.cx(pair[0], pair[1])\n",
        "\n",
        "# Choose a backend to run on\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy()\n",
        "\n",
        "# Transpile the circuit for execution\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
        "isa_circuit = pm.run(circuit)\n",
        "\n",
        "# Run the boxing pass manager to group instructions into annotated boxes\n",
        "boxing_pm = generate_boxing_pass_manager(\n",
        "    enable_gates=True,\n",
        "    enable_measures=False,\n",
        "    inject_noise_targets=\"gates\",  # no measurement mitigation\n",
        "    inject_noise_strategy=\"uniform_modification\",\n",
        ")\n",
        "boxed_circuit = boxing_pm.run(isa_circuit)\n",
        "\n",
        "# Find unique boxed instructions\n",
        "unique_box_instructions = find_unique_box_instructions(boxed_circuit.data)\n",
        "print(f\"Found {len(unique_box_instructions)} unique layers\")\n",
        "print(\n",
        "    f\"Each instruction is of type {type(unique_box_instructions[0].operation)}\"\n",
        ")\n",
        "print(\n",
        "    f\"And has annotations: {unique_box_instructions[0].operation.annotations}\"\n",
        ")\n",
        "\n",
        "# Instantiate a NoiseLearnerV3 object and execute the noise learning program\n",
        "learner = NoiseLearnerV3(backend)\n",
        "learner.options.shots_per_randomization = 128\n",
        "learner.options.num_randomizations = 32\n",
        "learner_job = learner.run(unique_box_instructions)\n",
        "learner_result = learner_job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "937986c1-b08d-4218-ae5d-c9dbfbf4a0cf",
      "metadata": {},
      "source": [
        "処理の結果は、オブジェクトの `NoiseLearnerV3Result` リストとなり、入力された各命令セットに対して1つずつ対応します。 `NoiseLearnerV3Result` には、ジェネレータやエラー率などを抽出するメソッドを持つオブジェクトを [`PauliLindbladMap`](/docs/api/qiskit/qiskit.quantum_info.PauliLindbladMap) 返すメソッドがあります `to_pauli_lindblad_map()` 。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "4a9b686b-cf8d-4986-8fff-83eedda1f2c1",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The Noise learner V3 result contains 3 entries and each has the following type:\n",
            " <class 'qiskit_ibm_runtime.results.noise_learner_v3.NoiseLearnerV3Result'>\n",
            "\n",
            "After converting to PauliLindbladMap, you can extract data  on the generators for the error channel (truncated to 3): \n",
            "<QubitSparsePauliList with 3 elements on 27 qubits: [X_0, Y_0, Z_0]>\n",
            "\n",
            "Along with the error rates (truncated to 3): \n",
            "[0.00026 0.00032 0.00023]\n",
            "\n"
          ]
        }
      ],
      "source": [
        "print(\n",
        "    f\"The Noise learner V3 result contains {len(learner_result)} entries\"\n",
        "    f\" and each has the following type:\\n {type(learner_result[0])}\\n\"\n",
        ")\n",
        "noise_map = learner_result[0].to_pauli_lindblad_map()\n",
        "print(\n",
        "    f\"After converting to PauliLindbladMap, you can extract data \"\n",
        "    f\" on the generators for the error channel \"\n",
        "    f\"(truncated to 3): \\n{noise_map.generators()[:3]}\\n\"\n",
        ")\n",
        "with numpy.printoptions(threshold=20):\n",
        "    print(\n",
        "        f\"Along with the error rates \"\n",
        "        f\"(truncated to 3): \\n{noise_map.rates[:3]}\\n\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "baa61d6a-7efc-498b-bccd-260871e174df",
      "metadata": {},
      "source": [
        "<span id=\"noise-learning-options\" />\n",
        "\n",
        "### ノイズ学習オプション\n",
        "\n",
        "`NoiseLearnerV3` ランダム化の回数やレイヤーペアの深さなど、いくつかのオプションに対応しています。 プリミティブ型と同様に、オブジェクトの `NoiseLearnerV3` インスタンス化中またはインスタンス化後にオプションを指定することができます。 前のコード例では、 および `num_randomizations` オプション `shots_per_randomization` の設定方法を示しました。 [`NoiseLearnerV3Options`](/docs/api/qiskit-ibm-runtime/options-models-noise-learner-v3-options) 詳細については、APIドキュメントを参照してください。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e76e997d-506f-4607-a89a-e4723c640a44",
      "metadata": {},
      "source": [
        "<span id=\"input-a-noise-model-to-executor\" />\n",
        "\n",
        "### Executorにノイズモデルを入力する\n",
        "\n",
        "Executorは、回路アノテーション（samplex形式）およびオプションで指定された設計意図に従います。 `InjectNoise` はノイズを挿入する場所を指定するための注釈であり、samplex 引 `pauli_lindblad_maps` 数は使用するノイズマップを指定します。\n",
        "\n",
        "前の例の回路は、命令を注釈付きのボックスにグループ化するボクシング・パス・マネージャーを経由します。 理解しやすくするために、関連するコードをここに記載します。\n",
        "\n",
        "* `inject_noise_targets=”gates”` エンタングラーを含むボックスに注釈 `InjectNoise` を追加するように指定します。\n",
        "* `inject_noise_strategy=\"uniform_modification\"` これは、 の注釈が付いた `InjectNoise` すべての同等のボックスに、同じ `ref` と `modifier_ref` を割り当てることを指定します。\n",
        "  * `InjectNoise.ref` そのボックスにノイズモデルを割り当てるために使用される一意の識別子です。\n",
        "  * `InjectNoise.modifier_ref` ボックスに割り当てられたノイズモデルを、乗数によってスケーリングできるようにします。\n",
        "\n",
        "```python\n",
        "boxing_pm = generate_boxing_pass_manager(\n",
        "    enable_gates=True,\n",
        "    enable_measures=False,\n",
        "    inject_noise_targets=\"gates\",  # no measurement mitigation\n",
        "    inject_noise_strategy=\"uniform_modification\",\n",
        ")\n",
        "```\n",
        "\n",
        "前の例の回路には3つのボックスが含まれており、そのうち2つには異なる `ref` 属性を持つ注釈が含まれています `InjectNoise` （これらは同等ではないため）。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "3b86853b-6766-4cf6-9a6b-2ea1008aea42",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Annotations of box #0: [Twirl(group='pauli', dressing='left', decomposition='rzsx'), InjectNoise(ref='r789B', modifier_ref='r789B', site='before')]\n",
            "\n",
            "Annotations of box #1: [Twirl(group='pauli', dressing='left', decomposition='rzsx'), InjectNoise(ref='r054B', modifier_ref='r054B', site='before')]\n",
            "\n",
            "Annotations of box #2: [Twirl(group='pauli', dressing='right', decomposition='rzsx')]\n",
            "\n"
          ]
        }
      ],
      "source": [
        "# box_circuit comes from the example above\n",
        "for idx, instruction in enumerate(boxed_circuit):\n",
        "    # The `InjectNoise` annotation defines which boxes to inject noise.\n",
        "    print(f\"Annotations of box #{idx}: {instruction.operation.annotations}\\n\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3ab1e503-b36a-46bd-b5d1-2735c3d0a82d",
      "metadata": {},
      "source": [
        "ジョブ `NoiseLearnerV3` の結果は、Executorに渡す前に辞書に変換する必要があります。 この辞書のキーは属性 `InjectNoise.ref` であり、値はそれに対応するノイズマップです。 このマッピングにより、Executorはどのノイズモデルをどこに注入すべきかがわかります。\n",
        "\n",
        "以下のコードでは、前の例で作成した回路と結果 `NoiseLearnerV3` を取り込み、それらをExecutorに渡す方法を示しています。Executorは、ノイズモデルを組み込んだ回路のバリエーションを生成し、ハードウェア上で実行します。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "96d59082-7adc-482a-b57f-0f7a5c3eb217",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime.quantum_program import QuantumProgram\n",
        "from samplomatic import build\n",
        "\n",
        "# Generate a quantum program\n",
        "program = QuantumProgram(shots=1000)\n",
        "\n",
        "# Build the template circuit and samplex pair\n",
        "template_circuit, samplex = build(boxed_circuit)\n",
        "\n",
        "# Convert the NoiseLearnerV3 result to a dictionary\n",
        "noise_maps = learner_result.to_dict(\n",
        "    instructions=unique_box_instructions, require_refs=False\n",
        ")\n",
        "\n",
        "# Append the samplex item and execute\n",
        "program.append_samplex_item(\n",
        "    template_circuit,\n",
        "    samplex=samplex,\n",
        "    samplex_arguments={\n",
        "        \"pauli_lindblad_maps\": noise_maps,\n",
        "    },\n",
        ")\n",
        "\n",
        "executor = Executor(backend)\n",
        "executor_job = executor.run(program)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "936c08fb-7838-4d61-9060-092b479e7909",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## 次のステップ\n",
        "\n",
        "<Admonition type=\"tip\" title=\"推奨事項\">\n",
        "  * [EstimatorOptions API リファレンスと](/docs/api/qiskit-ibm-runtime/options-estimator-options) [ResilienceOptionsV2 API リファレンスを](/docs/api/qiskit-ibm-runtime/options-resilience-options-v2)確認する。\n",
        "  * 利用可能な[エラーの軽減および抑制手法](error-mitigation-and-suppression-techniques)について、詳しくご覧ください。\n",
        "  * [Estimatorのノイズ管理](/docs/guides/estimator-noise-management)の実装方法について学びましょう。\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
}