{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "frontmatter",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"クイック・スタート\"\n",
        "description: \"Qiskitの最新バージョンにおける伝播型ノイズ吸収のクイックスタート\"\n",
        "---\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0b3182b6",
      "metadata": {},
      "source": [
        "<span id=\"quickstart\" />\n",
        "\n",
        "# クイック・スタート\n",
        "\n",
        "このガイドでは、この `qiskit-addon-pna` パッケージの最小限の動作例を紹介します。 我々は、伝播型騒音吸収（PNA）を用いて、騒音低減のための観測量を構築する。 ある回路とパウリ・リンドブラッド雑音モデルが与えられた場合、PNAは観測量を逆雑音チャネルを通じて古典的に伝播させる。 ノイズの混入したQPU上で結果として得られる観測量について測定を行うことで、学習されたゲートノイズを軽減することができる。\n",
        "\n",
        "`NoiseLearnerV3`「 [directed execution model](/docs/guides/directed-execution-model) 」を用いて現実的なワークフローを構築し、量子ハードウェア上で実行する方法（ノイズモデルの学習を含む）については、 IBM Quantum Platform[ のPNAチュートリアル](/docs/tutorials/propagated-noise-absorption)をご覧ください。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a4068f26",
      "metadata": {},
      "source": [
        "<span id=\"1-prepare-the-inputs-for-pna\" />\n",
        "\n",
        "## 1. PNA用の入力データを準備する\n",
        "\n",
        "PNAは、回路、ノイズモデル、および観測変数を入力として受け取ります。 ここでは、 1D 鎖上で、10キュービットのトロッター化横磁場イジングモデルを構築する。 各エンタングルメントゲートに対して、ランダムな2-ローカル・パウリ・リンドブラッドノイズモデルを生成し、そのゲートの直前にQiskit Aer `PauliLindbladError` の命令として埋め込みます。 測定対象として、 weight-4 のパウリ-Z観測量を選択する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "4a9a3ced",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/addons/qiskit-addon-pna/guides/quickstart/extracted-outputs/4a9a3ced-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "import numpy as np\n",
        "from qiskit import QuantumCircuit\n",
        "from qiskit.quantum_info import SparsePauliOp, pauli_basis\n",
        "from qiskit_aer.noise import PauliLindbladError\n",
        "\n",
        "\n",
        "def random_pauli_lindblad_noise(generators, seed, noise_scale=2e-3):\n",
        "    rates = np.random.default_rng(seed).random(len(generators)) * noise_scale\n",
        "    return PauliLindbladError(generators, rates)\n",
        "\n",
        "\n",
        "def ising_circuit(\n",
        "    num_qubits,\n",
        "    layers,\n",
        "    edge_noise=None,\n",
        "    *,\n",
        "    num_steps=3,\n",
        "    rx_angle=np.pi / 8,\n",
        "    rzz_angle=-np.pi / 2,\n",
        "):\n",
        "    \"\"\"Trotterized transverse-field Ising model; edge_noise=None gives the noiseless circuit.\"\"\"\n",
        "    qc = QuantumCircuit(num_qubits)\n",
        "    for _ in range(num_steps):\n",
        "        qc.rx(rx_angle, range(num_qubits))\n",
        "        for layer in layers:\n",
        "            for edge in layer:\n",
        "                if edge_noise is not None:\n",
        "                    qc.append(\n",
        "                        edge_noise[edge], edge\n",
        "                    )  # inject synthetic gate noise\n",
        "                qc.rzz(rzz_angle, *edge)\n",
        "    return qc\n",
        "\n",
        "\n",
        "num_qubits = 10\n",
        "\n",
        "# Two entangling layers per Trotter step: even and odd bonds of a 1D chain\n",
        "layers = [\n",
        "    [(i, i + 1) for i in range(0, num_qubits - 1, 2)],\n",
        "    [(i, i + 1) for i in range(1, num_qubits - 1, 2)],\n",
        "]\n",
        "edges = [edge for layer in layers for edge in layer]\n",
        "\n",
        "# Random 2-local Pauli-Lindblad noise, one instance per entangling gate\n",
        "two_qubit_paulis = SparsePauliOp(\n",
        "    [p for p in pauli_basis(2) if np.sum(p.x + p.z)]\n",
        ").paulis\n",
        "edge_noise = {\n",
        "    edge: random_pauli_lindblad_noise(two_qubit_paulis, seed=1234 + j)\n",
        "    for j, edge in enumerate(edges)\n",
        "}\n",
        "\n",
        "noisy_circuit = ising_circuit(num_qubits, layers, edge_noise)\n",
        "\n",
        "# A single weight-4 observable: <Z3 Z4 Z5 Z6>\n",
        "observable = SparsePauliOp.from_sparse_list(\n",
        "    [(\"ZZZZ\", [3, 4, 5, 6], 1.0)], num_qubits=num_qubits\n",
        ")\n",
        "\n",
        "noisy_circuit.draw(\"mpl\", fold=-1, scale=0.6)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b99617c3",
      "metadata": {},
      "source": [
        "<span id=\"2-generate-the-noise-mitigating-observable\" />\n",
        "\n",
        "## 2. ノイズ低減用観測量を生成する\n",
        "\n",
        "[generate\\_noise\\_mitigating\\_observable は、](/docs/api/qiskit-addon-pna/qiskit-addon-pna#generate_noise_mitigating_observable) 逆ノイズチャネルの各パウリ生成子を回路の末端まで順方向に伝播させます。 その後、観測値は逆ノイズチャネルを通じてバックプロパゲーションされ、新しい観測値 $\\tilde{O}$ が返されます。計算コストに影響を与える3つの主要なパラメータは以下の通りです：\n",
        "\n",
        "* `max_err_terms`: 前方伝播の際に、各アンチノイズ生成器に保持される項の数。\n",
        "* `max_obs_terms`: $\\tilde{O}$ に保持される項の数。\n",
        "* `atol`: この閾値より係数の絶対値が小さい項は除外される。\n",
        "\n",
        "`atol`このクリフォード回路に近い小さな回路については、項の制限を高く設定し、適度な値を用いることで、 $\\tilde{O}$ が小さく保たれ、そのすべての項を測定できるようになります。\n",
        "\n",
        "***`multiprocessing`注：この関数は を使用 Python します。 スクリプトとして実行する場合は、` `if **name** == \"**main**\":` guard` 内で呼び出してください。***\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "39891ec7",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Original observable:         1 term\n",
            "Noise-mitigating observable: 207 terms\n"
          ]
        }
      ],
      "source": [
        "from qiskit_addon_pna import generate_noise_mitigating_observable\n",
        "\n",
        "mitigating_observable = generate_noise_mitigating_observable(\n",
        "    noisy_circuit,\n",
        "    observable,\n",
        "    max_err_terms=100_000,\n",
        "    max_obs_terms=100_000,\n",
        "    atol=1e-5,\n",
        "    num_processes=4,\n",
        ")\n",
        "\n",
        "print(f\"Original observable:         {len(observable)} term\")\n",
        "print(f\"Noise-mitigating observable: {len(mitigating_observable)} terms\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f7881a9e",
      "metadata": {},
      "source": [
        "<span id=\"3-mitigate-gate-errors-by-measuring-the-noise-mitigating-observable\" />\n",
        "\n",
        "## 3. ノイズ低減観測量を測定することで、ゲートエラーを低減する\n",
        "\n",
        "ここでは、この新しい観測量によって、実験に影響を及ぼしていたゲートノイズが効果的に低減されていることがわかる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "a56dd204",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Ideal (noiseless):   0.8073\n",
            "Noisy (unmitigated): 0.6431\n",
            "Mitigated (PNA):     0.8071\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/addons/qiskit-addon-pna/guides/quickstart/extracted-outputs/a56dd204-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "from qiskit_aer.primitives import EstimatorV2\n",
        "\n",
        "noiseless_circuit = ising_circuit(num_qubits, layers)\n",
        "\n",
        "# density_matrix method at zero precision -> exact expectation values (no shot noise)\n",
        "estimator = EstimatorV2(\n",
        "    options={\n",
        "        \"backend_options\": {\"method\": \"density_matrix\"},\n",
        "        \"default_precision\": 0.0,\n",
        "    }\n",
        ")\n",
        "\n",
        "ideal, noisy, mitigated = (\n",
        "    result.data.evs\n",
        "    for result in estimator.run(\n",
        "        [\n",
        "            (noiseless_circuit, observable),\n",
        "            (noisy_circuit, observable),\n",
        "            (noisy_circuit, mitigating_observable),\n",
        "        ]\n",
        "    ).result()\n",
        ")\n",
        "\n",
        "print(f\"Ideal (noiseless):   {ideal:.4f}\")\n",
        "print(f\"Noisy (unmitigated): {noisy:.4f}\")\n",
        "print(f\"Mitigated (PNA):     {mitigated:.4f}\")\n",
        "\n",
        "fig, ax = plt.subplots()\n",
        "ax.bar(\n",
        "    [\"Noisy\", \"Mitigated\"],\n",
        "    [noisy, mitigated],\n",
        "    width=0.6,\n",
        "    color=[\"#b0b0b0\", \"#4c4c4c\"],\n",
        ")\n",
        "ax.axhline(ideal, color=\"green\", linestyle=\"--\", label=\"Ideal (noiseless)\")\n",
        "ax.set_ylabel(r\"$\\langle Z_3 Z_4 Z_5 Z_6 \\rangle$\")\n",
        "ax.legend()\n",
        "plt.show()"
      ]
    },
    {
      "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
}