{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "a10c2a41-ab48-4da5-bbe1-a16fd47906fe",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"西森相転移\"\n",
        "description: \"このチュートリアルでは、 IBM 量子プロセッサ上で西森相転移を実現する方法を示します。\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore Verresen Layden Tantivasadakarn Vishwanath Trebst */}\n",
        "\n",
        "<span id=\"nishimori-phase-transition\" />\n",
        "\n",
        "# 西森相転移\n",
        "\n",
        "*所要時間の目安：Heron r2 プロセッサで 3 分（注：これはあくまで目安です。 （実行時間は状況によって異なる場合があります。）*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6113a1ff-5cc0-433a-afd7-5aadc97bb28f",
      "metadata": {},
      "source": [
        "<span id=\"learning-outcomes\" />\n",
        "\n",
        "## 学習成果\n",
        "\n",
        "このチュートリアルを学習した後、ユーザーは以下の成果が得られるはずです：\n",
        "\n",
        "* 西森相転移とは何か、またそれがランダム結合アイジングモデルにおいて長距離エンタングルメントの出現としてどのように現れるかを理解する。\n",
        "* 回路中間測定と定深度回路を用いて、量子ハードウェア上で「 *測定によるエンタングルメント生成* （GEM）」プロトコルを実装する。\n",
        "* 実験データから磁化の2点相関および正規化分散を抽出し、この遷移の特徴を明らかにする。\n",
        "\n",
        "<span id=\"prerequisites\" />\n",
        "\n",
        "## 前提条件\n",
        "\n",
        "このチュートリアルを進める前に、以下のトピックについて理解しておくことをお勧めします：\n",
        "\n",
        "* 『 [Measure qubits](/docs/guides/measure-qubits) 』ガイド、特にGEMプロトコルが依存している回路途中測定に関するセクション。\n",
        "* [Qiskit Aerのプリミティブを用いた正確なシミュレーションとノイズを含むシミュレーション](/docs/guides/simulate-with-qiskit-aer)。小規模セクションはこの方法で実行されます。\n",
        "* 「[動的回路を用いた長距離エンタングルメント](/docs/tutorials/long-range-entanglement) 」：これは、同じ「測定に基づくエンタングルメント」のパラダイムを用いた関連チュートリアルです。\n",
        "* [ヘビーヘックス格子](https://www.ibm.com/quantum/blog/heavy-hex-lattice)。これは、プラケット格子が構築されている「 IBM® 」ハードウェアトポロジーである。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "838ac5c7-0819-4482-8875-c57db88ba82a",
      "metadata": {},
      "source": [
        "<span id=\"background\" />\n",
        "\n",
        "## 背景\n",
        "\n",
        "このチュートリアルでは、量子プロセッサ上で西森相転移を実現する方法を解説します。 この実験については、もともと [*『定深度量子回路におけるエラー閾値を超えた西森遷移の実現』*](https://arxiv.org/abs/2309.02863) という論文で報告された。\n",
        "\n",
        "西森相転移とは、ランダム結合アイジングモデルにおける短距離秩序相と長距離秩序相の間の相転移を指す。 量子コンピュータにおいて、長距離秩序相は、デバイス全体にわたって量子ビットがもつれ合った状態として現れる。 この高度に絡み合った状態は\\*、測定による絡み合い生成\\* （GEM）プロトコルを用いて生成される。 GEMプロトコルでは、回路中間測定を利用することで、深さが一定である回路のみを用いて、デバイス全体にわたって量子ビットをエンタングルメントさせることができる。 このチュートリアルでは[、GEM Suite](https://github.com/qiskit-community/gem-suite) ソフトウェアパッケージに含まれる GEM プロトコルの実装を使用します。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4091005d-ecd5-40c9-b90f-263e49a4cc16",
      "metadata": {},
      "source": [
        "<span id=\"requirements\" />\n",
        "\n",
        "## 要件\n",
        "\n",
        "このチュートリアルを始める前に、以下のものがインストールされていることを確認してください：\n",
        "\n",
        "* Qiskit SDK v1.0 またはそれ以降、 [可視化](/docs/api/qiskit/visualization)サポート付き\n",
        "* Qiskit Runtime v0.22 またはそれ以降 (`pip install qiskit-ibm-runtime`)\n",
        "* Qiskit Aer v0.14 以降 (`pip install qiskit-aer`)\n",
        "* GEM Suite (`pip install gem-suite`)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "210b8730-ca3e-46d9-b8b0-64c36f13df8e",
      "metadata": {},
      "source": [
        "<span id=\"setup\" />\n",
        "\n",
        "## セットアップ\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "4ad70734-54f8-400a-8399-188ee8a0f3ac",
      "metadata": {},
      "outputs": [],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "import warnings\n",
        "\n",
        "from collections import defaultdict\n",
        "\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "from qiskit_aer import AerSimulator\n",
        "\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "from gem_suite import PlaquetteLattice\n",
        "from gem_suite.experiments import GemExperiment"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "281ec87e-3f50-44b6-8e6f-a906b92fba74",
      "metadata": {},
      "source": [
        "<span id=\"small-scale-simulator-example\" />\n",
        "\n",
        "## 小規模シミュレータの例\n",
        "\n",
        "`AerSimulator`このセクションでは、ノイズレス環境におけるワークフロー全体について解説します。 プラケット格子は単一のプラケット（12キュービット）に限定されているため、シミュレーションの規模を小さくして高速に実行できる一方で、GEMプロトコルのあらゆる要素、すなわち回路中間測定、 $R_{ZZ}$ の角度掃引、デコード、および正規化分散解析を網羅的に検証することが可能である。 その後、このワークフローは、複数のプラケット、さらには実機上の格子全体へと拡張される。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "39f59f3a-eb2a-4160-9da2-2bb83c58771c",
      "metadata": {},
      "source": [
        "<span id=\"step-1-map-classical-inputs-to-a-quantum-problem\" />\n",
        "\n",
        "### ステップ1：古典的な入力を量子問題にマッピングする\n",
        "\n",
        "GEMプロトコルは、格子によって記述される量子ビットの接続性を備えた量子プロセッサ上で動作します。 現在の IBM Quantum® プロセッサでは[、ヘビーヘックス](https://www.ibm.com/quantum/blog/heavy-hex-lattice)格子が採用されています。 プロセッサ上の量子ビットは、格子内のどの単位セルを占めるかによって、 *プラケット*ごとにグループ分けされます。 量子ビットは複数の単位セルに存在し得るため、プラケットは互いに交わらないわけではない。 ヘビーヘックス格子では、1つのプラケットには12個の量子ビットが含まれています。 プラケット自体も格子を形成しており、2つのプラケットは、いずれかの量子ビットを共有している場合にのみ接続される。 ヘビーヘックス格子上では、隣接するプラケット間で3つの量子ビットが共有される。\n",
        "\n",
        "`PlaquetteLattice`GEM Suite ソフトウェアパッケージにおいて、GEM プロトコルを実装するための基本クラスは であり、これはプラケットの格子（ヘビーヘックス格子とは異なる）を表す。 A `PlaquetteLattice` は、量子ビット結合マップから初期化することができる。 現在、ヘビーヘックス・カップリングマップのみがサポートされています。\n",
        "\n",
        "以下のコードセルは、量子処理ユニット（QPU）の結合マップからプラケット格子を初期化します。 プラケット格子は、必ずしもハードウェア全体を網羅しているとは限りません。 例えば、 `ibm_torino` には合計133個の量子ビットがありますが、このデバイスに収まる最大のプラケット格子では、そのうち125個しか使用されておらず、18個のプラケットで構成されています。 `ibm_pittsburgh` また、（156量子ビット）も同様に、144量子ビットを21個のプラケットに収めています。 クビット数が異なる他のヘビーヘックスQPUについても、同様の傾向が見られる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "553dbafe-1778-4971-83c3-0408605b701d",
      "metadata": {},
      "outputs": [],
      "source": [
        "# QiskitRuntimeService.save_account(channel=\"ibm_quantum\", token=\"<YOUR_API_KEY>\", overwrite=True,\n",
        "# set_as_default=True)\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(\n",
        "    operational=True, simulator=False, min_num_qubits=127\n",
        ")\n",
        "aer_backend = AerSimulator.from_backend(backend)\n",
        "plaquette_lattice = PlaquetteLattice.from_coupling_map(backend.coupling_map)\n",
        "\n",
        "print(f\"Number of qubits in backend: {backend.num_qubits}\")\n",
        "print(\n",
        "    f\"Number of qubits in plaquette lattice: {len(list(plaquette_lattice.qubits()))}\"\n",
        ")\n",
        "print(f\"Number of plaquettes: {len(list(plaquette_lattice.plaquettes()))}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0bf43539-d782-44a9-ba4e-a1b6c7510803",
      "metadata": {},
      "source": [
        "プラケット格子のグラフ表現図を作成することで、プラケット格子を視覚化することができる。 図では、プラケットはラベル付きの六角形で表されており、2つのプラケットが量子ビットを共有していれば辺で結ばれている。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "625882a4-faeb-4d96-b441-c989f43c4dea",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/625882a4-faeb-4d96-b441-c989f43c4dea-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "plaquette_lattice.draw_plaquettes()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2f0a6b73-d1d2-4117-80cf-6fe3adbb82c5",
      "metadata": {},
      "source": [
        "`plaquettes` メソッドを使って、個々のプラケットに関する情報、例えばそれらが含む量子ビットを取得することができます。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "e412a612-c7d5-4689-840a-2383dd538f06",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "PyPlaquette(index=0, qubits=[3, 4, 5, 6, 7, 16, 17, 23, 24, 25, 26, 27], neighbors=[4, 3, 1])"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Get a list of the plaquettes\n",
        "plaquettes = list(plaquette_lattice.plaquettes())\n",
        "# Display information about plaquette 0\n",
        "plaquettes[0]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "75edf1b4-f95f-4ff7-9e3c-2e810711636f",
      "metadata": {},
      "source": [
        "また、プラケット格子を形成する基本的な量子ビットのダイアグラムを作成することもできます。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "a19d63ce-3572-4081-a008-c1332fbbe303",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/a19d63ce-3572-4081-a008-c1332fbbe303-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "plaquette_lattice.draw_qubits()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e7b0f54b-5bc2-42bb-b4d4-1346f0a902e3",
      "metadata": {},
      "source": [
        "量子ビットのラベルと、どの量子ビットが接続されているかを示す辺に加え、この図にはGEMプロトコルに関連する3つの情報が含まれている：\n",
        "\n",
        "* それぞれの量子ビットは、影付き（灰色）または影なしである。 斜線を引いた量子ビットは、イジングモデルのサイトを表す「サイト」量子ビットであり、斜線を引いていない量子ビットは、サイト量子ビット間の相互作用を媒介するための「ボンド」量子ビットである。\n",
        "* 各サイト量子ビットには(A)または(B)のラベルが付けられており、GEMプロトコルにおいてサイト量子ビットが果たしうる2つの役割のうちの1つを示している（役割については後で説明する）。\n",
        "* 各辺は6色のうちの1色で着色され、それによって辺は6つのグループに分けられる。 この分割方法によって、2量子ビットゲートの並列化の仕方が決まるほか、ノイズの多い量子プロセッサ上で異なるエラー率をもたらす可能性のある、さまざまなスケジューリングパターンも決定される。 グループ内の辺は互いに交わらないため、それらの辺に対して2量子ビットゲートの層を同時に適用することができる。 実際、6色を2色ずつ3つのグループに分けることが可能であり、その際、各2色のグループの和集合が依然として互いに素となるようにできる。 したがって、すべてのエッジをアクティブにするには、2量子ビットゲートを3層重ねるだけで十分である。 このように6色を分割する方法は12通りあり、それぞれの分割方法によって異なる3層ゲートスケジュールが得られる。\n",
        "\n",
        "プラケット格子を作成したところで、次のステップは、プラケット格子と、実験を実行する予定のバックエンドの両方を引数として渡して、`object` を `GemExperiment` 初期化することです。 この `GemExperiment` クラスは、回路の生成、ジョブの送信、データの分析など、GEMプロトコルの実際の実装を管理します。 以下のコードセルでは、実験クラスを初期化すると同時に、プラケット格子を単一のプラケット（12キュービット）に制限することで、シミュレーションの規模を小さくし、高速化を図っています。 実際のハードウェアへのスケールアップの際には、フルプラケット格子が使用されます。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "02357c6e-5c83-4ac0-811d-22602d9f33d5",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/02357c6e-5c83-4ac0-811d-22602d9f33d5-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Filter the plaquette lattice down to a single plaquette (12 qubits)\n",
        "# so the AerSimulator run stays fast. The full lattice is used later\n",
        "# in the large-scale hardware example.\n",
        "gem_exp = GemExperiment(plaquette_lattice.filter([9]), backend=aer_backend)\n",
        "\n",
        "# visualize the plaquette lattice after filtering\n",
        "plaquette_lattice.filter([9]).draw_qubits()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3234e018-a1a8-47b7-b10c-57d6f7f77ff1",
      "metadata": {},
      "source": [
        "GEMプロトコル回路は以下の手順で構築される：\n",
        "\n",
        "1. すべての量子ビットにハダマードゲートを適用して、 $|+\\rangle$ 状態を準備する。\n",
        "2. 接続されたすべての量子ビットのペアの間に、 $R_{ZZ}$ ゲートを適用します。 これを行うには、3層のゲートを使用します。 各 $R_{ZZ}$ ゲートは、サイト量子ビットと結合量子ビットに作用します。 サイト量子ビットにラベル (B) が付いている場合、角度は $\\frac{\\pi}{2}$ に固定されます。サイト量子ビットにラベル (A) が付いている場合、角度は変化可能であり、それによって異なる回路が生成されます。 デフォルトでは、角度の範囲は、 $0$ から $\\frac{\\pi}{2}$ までの間（両端を含む）を等間隔で分割した 21 箇所に設定されています。\n",
        "3. 各結合量子ビットを、パウリ $X$ 基底で測定する。 量子ビットはパウリ $Z$ 基底で測定されるため、量子ビットを測定する前にハダマールゲートを適用することで、これを実現できます。\n",
        "\n",
        "このチュートリアルの序章で引用されている論文では、 $R_{ZZ}$ 角度について、このチュートリアルで使用されている慣習とは 2 倍異なる慣習を使用していることに注意してください。\n",
        "\n",
        "ステップ3では、結合量子ビットのみを測定する。 サイト量子ビットがどのような状態にあるかを理解するには、ステップ2でサイト量子ビット（A）に印加された $R_{ZZ}$ の角度が $\\frac{\\pi}{2}$ に等しい場合を考えてみると参考になる。この場合、サイト量子ビットはGHZ状態に似た高度に絡み合った状態のままとなり、\n",
        "\n",
        "$$\n",
        "\\lvert \\text{GHZ} \\rangle = \\lvert 00 \\cdots 00 \\rangle + \\lvert 11 \\cdots 11 \\rangle.\n",
        "$$\n",
        "\n",
        "測定結果にはランダム性があるため、サイト量子ビットの実際の状態は、例えば $\\lvert 00110 \\rangle + \\lvert 11001 \\rangle$ のような長距離秩序を持つ別の状態である可能性もあります。しかし、測定結果に基づいて復号演算を行うことで、GHZ状態を復元することができます。 $R_{ZZ}$ の角度を $\\frac{\\pi}{2}$ から小さくしても、ノイズがない場合、臨界角度（およそ $0.3 \\pi$ ）までは長距離秩序が回復する。この角度を下回ると、その結果生じる状態はもはや長距離エンタングルメントを示さなくなる。 長距離秩序の有無の間のこの遷移が、西森相転移である。\n",
        "\n",
        "上記の説明では、サイト量子ビットは測定されずに残されており、量子ゲートを適用することで復号処理を行うことができます。 GEMスイートで実装された実験では、サイト量子ビットは実際に測定され、復号処理は古典的な後処理ステップで適用される。\n",
        "\n",
        "上記の説明では、各サイトの量子ビットに量子ゲートを適用することで復号操作を行い、量子状態を復元することができます。 ただし、状態を直ちに測定することが目的である場合（例えば、特性評価のためなど）、サイト量子ビットと結合量子ビットを一緒に測定し、古典的な後処理の段階で復号演算を適用することも可能です。\n",
        "\n",
        "GEMプロトコルの回路は、ステップ2における $R_{ZZ}$ の角度（デフォルトでは21個の値を走査する）に依存するだけでなく、 $R_{ZZ}$ ゲートの3層を実装するために使用されるスケジューリングパターンにも依存する。 前述したように、このようなスケジューリングパターンは12種類あります。 したがって、この実験における回路の総数は $21 \\times 12 = 252$ となる。\n",
        "\n",
        "`circuits` この実験の回路は、 クラスの `GemExperiment` メソッドを使用して生成することができます。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "8e2ade62-9a57-42c3-9a85-3fe2dec3c426",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Total number of circuits: 252\n"
          ]
        }
      ],
      "source": [
        "circuits = gem_exp.circuits()\n",
        "print(f\"Total number of circuits: {len(circuits)}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "56c3c656-dcfa-4ca0-9df9-2d97c187c685",
      "metadata": {},
      "source": [
        "このチュートリアルでは、一つのスケジューリング・パターンだけを考えれば十分である。 次のコード・セルは、実験を最初のスケジューリング・パターンに限定している。 その結果、実験には21個の回路しかなく、 $R_{ZZ}$ の角度ごとに1個ずつ掃引される。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "4f8a2c73-752d-47b9-95d5-83439933fc08",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Total number of circuits: 21\n",
            "RZZ angles:\n",
            "[0.         0.07853982 0.15707963 0.23561945 0.31415927 0.39269908\n",
            " 0.4712389  0.54977871 0.62831853 0.70685835 0.78539816 0.86393798\n",
            " 0.9424778  1.02101761 1.09955743 1.17809725 1.25663706 1.33517688\n",
            " 1.41371669 1.49225651 1.57079633]\n"
          ]
        }
      ],
      "source": [
        "# Restrict experiment to the first scheduling pattern\n",
        "gem_exp.set_experiment_options(schedule_idx=0)\n",
        "\n",
        "# There are less circuits now\n",
        "circuits = gem_exp.circuits()\n",
        "print(f\"Total number of circuits: {len(circuits)}\")\n",
        "\n",
        "# Print the RZZ angles swept over\n",
        "print(f\"RZZ angles:\\n{gem_exp.parameters()}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7011dc79-8561-42ef-909b-00fd8be9ef34",
      "metadata": {},
      "source": [
        "次のコード・セルは、インデックス5の回路の図を描いている。 図のサイズを小さくするため、回路の最後にある測定ゲートは取り除かれている。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "fd57d483-c70b-4ad5-b309-15750ad38bac",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/fd57d483-c70b-4ad5-b309-15750ad38bac-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Get the circuit at index 5\n",
        "circuit = circuits[5]\n",
        "# Remove the final measurements to ease visualization\n",
        "circuit.remove_final_measurements()\n",
        "# Draw the circuit\n",
        "circuit.draw(\"mpl\", fold=-1, scale=0.5)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a3aa063b-44cf-49f3-9e12-23b2f6a1c85b",
      "metadata": {},
      "source": [
        "<span id=\"step-2-optimize-problem-for-quantum-hardware-execution\" />\n",
        "\n",
        "### ステップ2：量子ハードウェア実行に向けた問題の最適化\n",
        "\n",
        "ハードウェア上で実行するために量子回路をトランスパイルするには、通常[、いくつかの段階](/docs/guides/transpiler-stages)を経る必要がある。 通常、最も計算負荷がかかる段階は、量子ビットの配置の決定、ハードウェアの量子ビット接続構成に合わせて2量子ビットゲートを配線すること、およびゲート数と深さを最小限に抑えるための回路の最適化である。 GEMプロトコルでは、ハードウェアの接続性がすでにプロトコルの設計に組み込まれているため、レイアウトおよび配線段階は不要である。 回路にはすでに量子ビットの配置が定められており、2量子ビットゲートはすでにネイティブ接続にマッピングされています。 さらに、 $R_{ZZ}$ の角度が変化しても回路の構造を維持するためには、ごく基本的な回路の最適化のみを行うべきである。\n",
        "\n",
        "`GemExperiment` クラスは、実験実行時に回路を透過的にトランスパイルする。 レイアウトと配線ステージはすでにデフォルトで何もしないように上書きされており、回路の最適化は単一量子ビットゲートのみを最適化するレベルで実行される。 しかし、 `set_transpile_options` メソッドを使えば、追加のオプションを上書きしたり、渡したりすることができる。 視覚化のために、次のコード・セルは、先に表示された回路を手動でトランスパイルし、トランスパイルされた回路を描画する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "e9b99d48-8d33-46b5-bff5-480ab1c1c1f2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/e9b99d48-8d33-46b5-bff5-480ab1c1c1f2-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Demonstrate setting transpile options\n",
        "gem_exp.set_transpile_options(\n",
        "    optimization_level=1  # This is the default optimization level\n",
        ")\n",
        "pass_manager = generate_preset_pass_manager(\n",
        "    backend=aer_backend,\n",
        "    initial_layout=list(gem_exp.physical_qubits),\n",
        "    **dict(gem_exp.transpile_options),\n",
        ")\n",
        "transpiled = pass_manager.run(circuit)\n",
        "transpiled.draw(\"mpl\", idle_wires=False, fold=-1, scale=0.5)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8d0dcd59-54ef-4af8-9213-0784ef94b838",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute-using-qiskit-primitives\" />\n",
        "\n",
        "### ステップ3: `Qiskit primitives`を使用して実行する\n",
        "\n",
        "ハードウェア上でGEMプロトコル回路を実行するには、 `GemExperiment` オブジェクトの `run` メソッドを呼び出します。 各回路からサンプリングするショット数を指定できます。 `run` メソッドは [ExperimentData](https://qiskit-community.github.io/qiskit-experiments/stubs/qiskit_experiments.framework.ExperimentData.html) オブジェクトを返します。 `run` メソッドは、ジョブの終了を待たずにジョブを投入するだけなので、ノンブロッキング・コールであることに注意。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "6171a383-dd58-4e3f-88aa-bbec7b5870df",
      "metadata": {},
      "outputs": [],
      "source": [
        "exp_data = gem_exp.run(shots=10_000)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "71e81552-0d33-4950-8d45-e6c0a8a056c9",
      "metadata": {},
      "source": [
        "結果を待つには、 `ExperimentData` オブジェクトの `block_for_results` メソッドを呼び出す。 この呼び出しは、ジョブが終了するまでインタープリターをハングアップさせる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "ed14a067-35ba-4ffc-8534-4ae5ec6bc4c9",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "ExperimentData(GemExperiment, 90bf2a90-f729-4c4e-a6da-664aecb11039, job_ids=['04a7c405-47fd-46ca-aa4b-aaf7e339cfbe'], metadata=<5 items>, figure_names=['two_point_correlation.svg', 'normalized_variance.svg', 'plaquette_ops.svg', 'bond_ops.svg'])"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# The noiseless AerSimulator produces zero-variance UFloat objects in the\n",
        "# analysis, which triggers a harmless warning from the `uncertainties`\n",
        "# library. Suppress it so the output stays clean.\n",
        "with warnings.catch_warnings():\n",
        "    warnings.filterwarnings(\n",
        "        \"ignore\", message=\"Using UFloat objects with std_dev==0\"\n",
        "    )\n",
        "    exp_data.block_for_results()\n",
        "exp_data"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "36e0570b-f091-45f2-bb83-143edbc3b433",
      "metadata": {},
      "source": [
        "<span id=\"step-4-post-process-and-return-result-in-desired-classical-format\" />\n",
        "\n",
        "### ステップ4：後処理を行い、結果を希望の古典形式で返す\n",
        "\n",
        "$R_{ZZ}$ 角度 $\\frac{\\pi}{2}$ では、復号化された状態は、ノイズがない場合のGHZ状態となる。 GHZ状態の長距離秩序は、測定されたビット列の磁化をプロットすることで可視化できる。 磁化 $M$ は、1量子ビットのパウリ $Z$ 演算子の和として定義される、\n",
        "\n",
        "$$\n",
        "M = \\sum_{j=1}^N Z_j,\n",
        "$$\n",
        "\n",
        "ここで、 $N$ はサイト量子ビットの数である。 ビット列に対するその値は、0の個数と1の個数の差に等しい。 GHZ状態を測定すると、等しい確率で「すべて0」の状態または「すべて1」の状態が得られるため、磁化は半分の時間では $+N$ となり、残りの半分の時間では $-N$ となる。 ノイズによる誤差がある場合、他の値も現れるが、ノイズがそれほど大きくない限り、分布のピークは依然として $+N$ および $-N$ 付近に現れるだろう。\n",
        "\n",
        "デコード前の生のビット列の場合、磁化の分布は、ノイズがなければ、一様にランダムなビット列の分布と同じになる。\n",
        "\n",
        "以下のコードセルは、生のビット列とデコードされたビット列の磁化を、 $R_{ZZ}$ の角度（ $\\frac{\\pi}{2}$ ）でプロットしたものである。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "8ead3582-16df-4616-836c-bdce867ad6b8",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "Text(0.5, 1.0, 'Magnetization distribution with and without decoding')"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/8ead3582-16df-4616-836c-bdce867ad6b8-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "def magnetization_distribution(\n",
        "    counts_dict: dict[str, int],\n",
        ") -> dict[str, float]:\n",
        "    \"\"\"Compute magnetization distribution from counts dictionary.\"\"\"\n",
        "    # Construct dictionary from magnetization to count\n",
        "    mag_dist = defaultdict(float)\n",
        "    for bitstring, count in counts_dict.items():\n",
        "        mag = bitstring.count(\"0\") - bitstring.count(\"1\")\n",
        "        mag_dist[mag] += count\n",
        "    # Normalize\n",
        "    shots = sum(counts_dict.values())\n",
        "    for mag in mag_dist:\n",
        "        mag_dist[mag] /= shots\n",
        "    return mag_dist\n",
        "\n",
        "\n",
        "# Get counts dictionaries with and without decoding\n",
        "data = exp_data.data()\n",
        "# Get the last data point, which is at the angle for the GHZ state\n",
        "raw_counts = data[-1][\"counts\"]\n",
        "# Without decoding\n",
        "site_indices = [\n",
        "    i for i, q in enumerate(gem_exp.plaquettes.qubits()) if q.role == \"Site\"\n",
        "]\n",
        "site_raw_counts = defaultdict(int)\n",
        "for key, val in raw_counts.items():\n",
        "    site_str = \"\".join(key[-1 - i] for i in site_indices)\n",
        "    site_raw_counts[site_str] += val\n",
        "# With decoding\n",
        "_, site_decoded_counts = gem_exp.plaquettes.decode_outcomes(\n",
        "    raw_counts, return_counts=True\n",
        ")\n",
        "\n",
        "# Compute magnetization distribution\n",
        "raw_magnetization = magnetization_distribution(site_raw_counts)\n",
        "decoded_magnetization = magnetization_distribution(site_decoded_counts)\n",
        "\n",
        "# Plot\n",
        "plt.bar(*zip(*raw_magnetization.items()), label=\"raw\")\n",
        "plt.bar(*zip(*decoded_magnetization.items()), label=\"decoded\", width=0.3)\n",
        "plt.legend()\n",
        "plt.xlabel(\"Magnetization\")\n",
        "plt.ylabel(\"Frequency\")\n",
        "plt.title(\"Magnetization distribution with and without decoding\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "90a7ae7a-5175-421f-bda9-bc6b986bdf5f",
      "metadata": {},
      "source": [
        "長距離秩序をより厳密に特徴付けるために、平均2点相関 $f$ を調べることができる\n",
        "\n",
        "$$\n",
        "f = \\frac{1}{N^2} \\left(\\langle M^2 \\rangle - \\langle M \\rangle ^2\\right).\n",
        "$$\n",
        "\n",
        "値が大きいほど、もつれの程度が大きいことを示す。 `GemExperiment` クラスは、実験データ処理の一環として、デコードされたビット列に対してこの値を自動的に計算する。 実験データクラスの `figure` メソッドからアクセス可能な図が格納されている。 この場合、図の名前は `two_point_correlation` となる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "4ecb25c8-e572-49af-a879-9943039db131",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/4ecb25c8-e572-49af-a879-9943039db131-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 14,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "exp_data.figure(\"two_point_correlation\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f2f3e7e2-2a8b-4790-8ba7-b190c4ed1049",
      "metadata": {},
      "source": [
        "西森の相転移の臨界点を決定するには、 $M^2 / N$ の正規化された分散を見ることができる\n",
        "\n",
        "$$\n",
        "g = \\frac{1}{N^3} \\left(\\langle M^4 \\rangle - \\langle M^2 \\rangle^2\\right),\n",
        "$$\n",
        "\n",
        "これは磁化の二乗の揺らぎの大きさを定量化したものである。 この値は、西森相転移の臨界点で最大となる。 ノイズがない場合、臨界点はおよそ $0.3 \\pi$ で発生する。ノイズがある場合、臨界点は高くシフトするが、臨界点が $0.5 \\pi$ 以下で発生する限り、相転移は観察される。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "2b351d68-3924-445a-94ef-047b16214e8a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/2b351d68-3924-445a-94ef-047b16214e8a-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 15,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "exp_data.figure(\"normalized_variance\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a94e0cbe-8429-487c-b203-50a8b2eacee3",
      "metadata": {},
      "source": [
        "<span id=\"large-scale-hardware-example\" />\n",
        "\n",
        "## 大規模なハードウェアの例\n",
        "\n",
        "シミュレータ上でプロトコルの検証が完了したら、実験をスケールアップし、 「[セットアップ](#setup) 」セクションで選択した実際の量子ハードウェア・バックエンド上で実行することができます。 この例では、2つのより大きな問題サイズを使用しています：\n",
        "\n",
        "* **6枚のプラケット（約49キュービット）** ：ハードウェアノイズ下において、臨界点が右側にシフトしていることがすでに確認できる中規模の実験。\n",
        "* **完全プラケット格子** ：デバイスの「ヘビー・ヘックス」トポロジーがサポートするすべてのプラケット（例えば、18プラケット／125キュービットの `ibm_torino` や、21プラケット／144キュービットの `ibm_pittsburgh`など）において、定深度回路を用いてデバイス全体にわたってキュービットをエンタングルさせる。\n",
        "\n",
        "以下の単一のコードセルは独立して動作します。バックエンドの結合マップからプラケット格子を構築し、両方の実験を実行するため、このセクションは、小規模セクションを先に実行することなく、「 [Setup](#setup) 」セルの後に実行することができます。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "08581c09-a6a5-4a56-9fc4-abf22b063c6a",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Total number of circuits (full lattice): 21\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-2.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-3.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 16,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# -------------------------Step 1-------------------------\n",
        "# Initialize the runtime service, pick a real quantum hardware backend,\n",
        "# and build the plaquette lattice from its coupling map. This is repeated\n",
        "# from the small-scale example so this cell can run standalone after the\n",
        "# Setup section. The full plaquette lattice is the \"large-scale\" target;\n",
        "# a six-plaquette subset (range(3, 9)) is also used to show an intermediate\n",
        "# scaling step.\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(\n",
        "    operational=True, simulator=False, min_num_qubits=127\n",
        ")\n",
        "plaquette_lattice = PlaquetteLattice.from_coupling_map(backend.coupling_map)\n",
        "\n",
        "# Build a GemExperiment for the full plaquette lattice and one for the\n",
        "# six-plaquette subset, each restricted to a single scheduling pattern so\n",
        "# the experiment has one circuit per RZZ angle (21 circuits total).\n",
        "gem_exp_full = GemExperiment(plaquette_lattice, backend=backend)\n",
        "gem_exp_full.set_experiment_options(schedule_idx=0)\n",
        "gem_exp_6 = GemExperiment(\n",
        "    plaquette_lattice.filter(range(3, 9)), backend=backend\n",
        ")\n",
        "gem_exp_6.set_experiment_options(schedule_idx=0)\n",
        "\n",
        "circuits = gem_exp_full.circuits()\n",
        "print(f\"Total number of circuits (full lattice): {len(circuits)}\")\n",
        "\n",
        "# -------------------------Step 2-------------------------\n",
        "# GemExperiment transpiles internally for the target backend: the layout\n",
        "# and routing stages are overridden because the plaquette lattice already\n",
        "# matches the hardware connectivity, and optimization is restricted so the\n",
        "# RZZ angle structure is preserved. The code below manually transpiles one\n",
        "# circuit from the six-plaquette experiment with the same settings this\n",
        "# experiment will use, and draws it for inspection. (The full-lattice\n",
        "# transpiled circuit has too many qubits to visualize cleanly, so the\n",
        "# six-plaquette circuit is used here as a representative example.)\n",
        "gem_exp_6.set_transpile_options(optimization_level=1)\n",
        "circuits_6 = gem_exp_6.circuits()\n",
        "pass_manager = generate_preset_pass_manager(\n",
        "    backend=backend,\n",
        "    initial_layout=list(gem_exp_6.physical_qubits),\n",
        "    **dict(gem_exp_6.transpile_options),\n",
        ")\n",
        "transpiled = pass_manager.run(circuits_6[5])\n",
        "display(transpiled.draw(\"mpl\", idle_wires=False, fold=-1, scale=0.5))\n",
        "\n",
        "# -------------------------Step 3-------------------------\n",
        "# Run both problem sizes on real hardware:\n",
        "#   1. Six plaquettes (~49 qubits) — an intermediate scale-up.\n",
        "#   2. The full plaquette lattice — every plaquette the device supports.\n",
        "exp_data_6 = gem_exp_6.run(shots=10_000, job_tags=[\"TUT_NPT\"])\n",
        "exp_data_full = gem_exp_full.run(shots=10_000, job_tags=[\"TUT_NPT\"])\n",
        "exp_data_6.block_for_results()\n",
        "exp_data_full.block_for_results()\n",
        "\n",
        "# -------------------------Step 4-------------------------\n",
        "# Plot the normalized variance at each scale. The peak marks the critical\n",
        "# point of the Nishimori transition; as the system grows, hardware noise\n",
        "# shifts the peak rightward.\n",
        "display(exp_data_6.figure(\"normalized_variance\"))\n",
        "exp_data_full.figure(\"normalized_variance\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "da03c8eb-5ec5-4c9c-8eb7-d44c5948b43c",
      "metadata": {},
      "source": [
        "なお、使用するバックエンドのノイズレベルによっては、大きなサイズにおける正規化分散曲線は、掃引角度の範囲内で明確なピークを示さない場合があることに留意してください。 上記の実行結果では、ピークは $0.5 \\pi$ まで押し上げられており、これはスイープの右端に相当します（6プラケットおよびフルラティスの両方の実行結果に関する解析レポート `critical_angle = 0.5000` ）。 これは、ハードウェアノイズによって臨界点が、プロトコルの物理的に意味のある角度範囲の境界（またはそのすぐ先）へとずれてしまったことを意味し、そのため、この遷移は、このスイープで分解能が得られる範囲の限界付近に位置することになります。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6abd9701-58e4-43a8-a1d7-279506570de4",
      "metadata": {},
      "source": [
        "<span id=\"conclusion\" />\n",
        "\n",
        "## おわりに\n",
        "\n",
        "このチュートリアルでは、GEMプロトコルを用いて、量子プロセッサ上で西森相転移を実現しました。 後処理の過程で検討した指標、とりわけ2点相関係数と正規化分散は、この装置が長距離の量子もつれ状態を生成する能力の指標となります。 これらのベンチマークにより、GEMプロトコルの有用性は、興味深い物理現象の解明にとどまらず、さらに広がることになる。 このプロトコルの一環として、深さが定数である回路のみを用いて、デバイス全体にわたって量子ビットをエンタングルメントさせました。 この成果は、プロトコルが回路中間測定を採用しているからこそ可能となったものである。 この実験では、量子もつれ状態は直ちに測定されましたが、この状態をさらなる量子処理に活用して、さらに研究を進めてみるのも一案でしょう。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "717f22c6-4945-4719-b9ba-ae44cde58da8",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## 次のステップ\n",
        "\n",
        "<Admonition type=\"tip\" title=\"推奨事項\">\n",
        "  この作品に興味を持たれた方は、以下の資料もご参照ください：\n",
        "\n",
        "  * [動的回路を用いた長距離エンタングルメント](/docs/tutorials/long-range-entanglement)\n",
        "  * [繰り返しコード](/docs/tutorials/repetition-codes)\n",
        "  * [古典的なフィードフォワードと制御フロー](/docs/guides/classical-feedforward-and-control-flow)\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bf0dc8db-004f-4567-8162-f09be453b434",
      "metadata": {},
      "source": [
        "<span id=\"references\" />\n",
        "\n",
        "## 参照\n",
        "\n",
        "\\[1] E. H. Chen, 『 G.-Y 』. Zhu, R.、Verresen, A.、Seif, E.、Bäumer, D.、Layden, N.、Tantivasadakarn, G.、Zhu, S.、Sheldon, A.、Vishwanath, S.、Trebst, A.、Kandala. *定深度量子回路における西森遷移のエラー閾値超えの実現。* [arXiv:2309.02863](https://arxiv.org/abs/2309.02863) (2023)。\n",
        "\n",
        "\\[2] [GEM Suite](https://github.com/qiskit-community/gem-suite) ソフトウェアパッケージ。\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"
    },
    "hours": 1,
    "qpuSeconds": 180
  },
  "nbformat": 4,
  "nbformat_minor": 4
}