{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "frontmatter",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"クイック・スタート\"\n",
        "description: \"Qiskit Paulice 最新バージョンのクイックスタート\"\n",
        "---\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "intro",
      "metadata": {},
      "source": [
        "<span id=\"quickstart\" />\n",
        "\n",
        "# クイック・スタート\n",
        "\n",
        "このガイドでは、この `qiskit-paulice` パッケージの最小限の動作例を紹介します。 我々は、クリフォード回路の実行中にエラーを検出するために[時空間パウリチェック](https://arxiv.org/abs/2504.15725)を用い、その後、エラーが検出されなかったサンプルのみを事後選択する。 忠実度の向上を定量的に示す、より詳しいエンドツーエンドのワークフローについては、 [詳細なチュートリアル](https://github.com/Qiskit/qiskit-paulice/blob/main/docs/guides/low_overhead_error_detection_using_spacetime_codes.ipynb)をご覧ください。\n",
        "\n",
        "**ワークフロー・ステップ**\n",
        "\n",
        "1. 入力の準備を行います：クリフォード・ペイロード回路、チェック演算を実行するターゲット／アンシラ量子ビット、およびノイズモデルです。\n",
        "2. 適切な時空パウリチェックを見つけ、それらを回路に追加する。\n",
        "3. チェック済みの回路をサンプルとして確認してください。\n",
        "4. エラーが検出されなかったサンプルのみを抽出してください。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "build-circuit",
      "metadata": {},
      "source": [
        "<span id=\"1-prepare-the-inputs\" />\n",
        "\n",
        "## 1. 入力データの準備\n",
        "\n",
        "`add_pauli_checks` 少なくとも1つの端子測定を含むクリフォード**回路**、チェックの実装に使用される**ターゲット量子ビット**、および候補となるチェックの評価に用いられる**ノイズモデル**を受け取る。 `ibm_boston`ここでは、浅いランダムなクリフォード回路を構築し、 1D の物理量子ビットチェーン上に配置し、各ペイロード量子ビットを隣接するアンシラとペアリングし（これにより、チェックにはSWAPゲートが不要となる）、バックエンドのベンチマークデータから大まかな脱分極ノイズモデルを推定する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "make-circuit",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/addons/qiskit-addon-paulice/guides/quickstart/extracted-outputs/make-circuit-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_ibm_runtime import QiskitRuntimeService\n",
        "from qiskit_paulice.layout import get_check_qubits\n",
        "from qiskit_paulice.noise_models import NoiseModel\n",
        "\n",
        "# Backend and a 1D chain of physical qubits to run on\n",
        "backend = QiskitRuntimeService().backend(\"ibm_boston\")\n",
        "layout = [68, 69, 78, 89, 90, 91, 98, 111, 112, 113, 119, 133]\n",
        "\n",
        "# A shallow brickwork random Clifford payload circuit\n",
        "rng = np.random.default_rng(1764)\n",
        "circuit = QuantumCircuit(len(layout))\n",
        "circuit.h(range(circuit.num_qubits))\n",
        "for d in range(4):\n",
        "    for i in range(d % 2, circuit.num_qubits - 1, 2):\n",
        "        circuit.cz(i, i + 1)\n",
        "    for q in range(circuit.num_qubits):\n",
        "        if rng.integers(0, 2):\n",
        "            circuit.sx(q)\n",
        "        if rng.integers(0, 2):\n",
        "            circuit.s(q)\n",
        "circuit.measure_all()\n",
        "\n",
        "# Pair each payload qubit with a neighboring ancilla to host a check (no SWAPs needed)\n",
        "target_qubits, ancilla_qubits = get_check_qubits(backend.coupling_map, layout)\n",
        "\n",
        "# A rough depolarizing noise model from backend benchmark data, used to score checks\n",
        "noise_model = NoiseModel.from_backend(\n",
        "    backend, layout, uniform_gate_noise=True\n",
        ")\n",
        "\n",
        "circuit.draw(\"mpl\", fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "add-checks-md",
      "metadata": {},
      "source": [
        "<span id=\"2-find-and-add-spacetime-pauli-checks\" />\n",
        "\n",
        "## 2. 時空パウリチェックを検索して追加する\n",
        "\n",
        "`add_pauli_checks` 各ターゲット量子ビットに対して、効果的で低重みのチェックを検索し、それらを回路に追加して、一連の `CheckedCircuit` インスタンスを返す。 各インスタンスには `CheckedCircuit` 、チェックの数が徐々に増えており、チェックから `0` 、ターゲット量子ビット1つにつき1回のチェックまで含まれています。 各チェックは、回路の深さがわずかに増えるという代償を払う代わりに、エラー検出能力を向上させます。 この例では、すべてのターゲット量子ビットに対してチェックを行う回路を使用します。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "add-checks",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/addons/qiskit-addon-paulice/guides/quickstart/extracted-outputs/add-checks-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit_paulice import add_pauli_checks\n",
        "\n",
        "# The circuit has virtual qubits, so we specify our target qubits with virtual indices\n",
        "target_qubits_v = [layout.index(q) for q in target_qubits]\n",
        "\n",
        "# Add spacetime Pauli checks\n",
        "checked_circuit = add_pauli_checks(circuit, target_qubits_v, noise_model)[-1]\n",
        "checked_circuit.circuit.draw(\"mpl\", fold=-1, scale=0.4, idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "postselect-md",
      "metadata": {},
      "source": [
        "<span id=\"3-sample-the-checked-circuit\" />\n",
        "\n",
        "## 3. チェック済みの回路のサンプルを取得する\n",
        "\n",
        "`ibm_boston`サンプリングを行う前に、検証済みの回路を物理量子ビット（`initial_layout = layout + ancilla_qubits`）上にトランスパイルし、のネイティブ基底ゲートセットに変換します。 ノイズの多いQPUをエミュレートするために、チェックの選択に使用されたもの `noise_model` と同じエラー率を持つ、ノイズの多いAerスタビライザーバックエンドを用いてサンプリングを行う。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "sample",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "sampled 1000 shots\n"
          ]
        }
      ],
      "source": [
        "from qiskit import transpile\n",
        "from qiskit_aer import AerSimulator\n",
        "from qiskit_aer.noise import NoiseModel as AerNoiseModel\n",
        "from qiskit_aer.noise import ReadoutError, depolarizing_error\n",
        "\n",
        "# Transpile once: lay the checked circuit out on our qubits and into the native basis\n",
        "isa_circuit = transpile(\n",
        "    checked_circuit.circuit,\n",
        "    backend,\n",
        "    initial_layout=layout + ancilla_qubits,\n",
        "    optimization_level=0,\n",
        ")\n",
        "\n",
        "# Build an Aer noise model matching the depolarizing model used to pick checks\n",
        "aer_noise = AerNoiseModel()\n",
        "aer_noise.add_all_qubit_quantum_error(\n",
        "    depolarizing_error(noise_model.gate_noise, 2), [\"cz\"]\n",
        ")\n",
        "p = noise_model.readout_noise\n",
        "aer_noise.add_all_qubit_readout_error(ReadoutError([[1 - p, p], [p, 1 - p]]))\n",
        "simulator = AerSimulator(method=\"stabilizer\", noise_model=aer_noise)\n",
        "\n",
        "counts = (\n",
        "    simulator.run(isa_circuit, shots=1000, seed_simulator=1764)\n",
        "    .result()\n",
        "    .get_counts()\n",
        ")\n",
        "print(f\"sampled {sum(counts.values())} shots\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "postselect-step-md",
      "metadata": {},
      "source": [
        "<span id=\"4-postselect-samples-with-no-detected-error\" />\n",
        "\n",
        "## 4. エラーが検出されなかったポストセレクトサンプル\n",
        "\n",
        "`get_postselection_method` 各ショットをそのシンドロームベクトルに対応付けます。シンドロームがすべてゼロのショット、つまりどのチェックでもエラーが検出されなかったショットのみを保持します。 フラグが立てられたショットを排除することで、検出されたエラーが残存する分布から除去され、サンプリングレートは低下するものの、その忠実度は向上する。 定量的な忠実度の比較については[、チュートリアル](https://github.com/Qiskit/qiskit-paulice/blob/main/docs/guides/low_overhead_error_detection_using_spacetime_codes.ipynb)をご覧ください。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "postselect",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "kept 927 of 1000 shots (93%)\n"
          ]
        }
      ],
      "source": [
        "# Keep only the shots in which no check reported an error\n",
        "ps_fn = checked_circuit.get_postselection_method()\n",
        "counts_postselected = {\n",
        "    bs: n for bs, n in counts.items() if not ps_fn(bs).any()\n",
        "}\n",
        "\n",
        "kept, total = sum(counts_postselected.values()), sum(counts.values())\n",
        "print(f\"kept {kept} of {total} shots ({kept / total:.0%})\")"
      ]
    },
    {
      "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
}