{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "8d86bf32",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"横磁場アイジングモデルの時間発展をシミュレートする\"\n",
        "description: \"Qiskit.jl を使用して、 IBM Quantum ハードウェア上で横磁場アイジングモデルの時間発展をシミュレーションする\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore mktempdir Néel spdiagm Runge Kutta tspan saveat Neel maxdim tensornetworkstate println clims xlabel ylabel colorbar juliaup vcat nsteps ylims topright findfirst */}\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "65550e2a",
      "metadata": {},
      "source": [
        "<span id=\"simulate-time-evolution-of-the-transverse-field-ising-model\" />\n",
        "\n",
        "# 横磁場アイジングモデルの時間発展をシミュレートする\n",
        "\n",
        "推定*実行時間：Nighthawk r2 プロセッサで 105 秒（注：これはあくまで推定値です。 （実行時間は状況によって異なる場合があります。）*\n",
        "\n",
        "<span id=\"learning-outcomes\" />\n",
        "\n",
        "## 学習成果\n",
        "\n",
        "1. Julia を使って、量子回路をトランスパイルし、ハードウェア上で実行する方法を学びましょう\n",
        "2. 測定結果の後処理を行い、期待値を算出する方法について学びましょう\n",
        "3. 従来のシミュレーション結果とハードウェアの結果を比較評価し、トロッター近似誤差とハードウェアノイズの複合的な影響を定量化する方法を学びます\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "efde28b8",
      "metadata": {},
      "source": [
        "<span id=\"prerequisites\" />\n",
        "\n",
        "## 前提条件\n",
        "\n",
        "このチュートリアルを始める前に、以下のトピックについて理解しておいてください：\n",
        "\n",
        "* [量子シミュレーション](/learning/courses/utility-scale-quantum-computing/quantum-simulation)\n",
        "\n",
        "* [横磁場イジングモデル](https://en.wikipedia.org/wiki/Transverse-field_Ising_model)\n",
        "\n",
        "* [トランスピレーションの概要](/docs/guides/transpile#introduction-to-transpilation)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "727912c7",
      "metadata": {},
      "source": [
        "<span id=\"background\" />\n",
        "\n",
        "## 背景\n",
        "\n",
        "Juliaは、主に数値計算や科学計算を目的として設計された動的プログラミング言語です。 その高性能な数値計算能力により、量子シミュレーションのワークフローに最適です。 このチュートリアルでは、Julia を用いて、従来のプリプロセッシングやポストプロセッシング（例えば、ハミルトニアンの構築、常微分方程式（ODE）ソルバーの実行、期待値の計算など）を行う方法と、量子ハードウェアジョブの調整を行う方法を紹介します。これにより、言語や環境を切り替える必要がなくなります。\n",
        "\n",
        "Juliaから IBM Quantum® ハードウェアと連携するために、このチュートリアルではQiskitエコシステムに属する2つのパッケージを使用します。1つはQiskit Cライブラリをラップ `Qiskit.jl` し、Juliaでの回路構築およびトランスパイル機能を提供するものです。もう1つは、 IBM Quantum Compute サービスクライアントを介して IBM Quantum ハードウェアに接続し `QiskitIBMRuntime.jl` 、Juliaから直接ジョブの送信や結果の取得を可能にするものです。\n",
        "\n",
        "このチュートリアルでは、 1D 鎖上で、最近接相互作用を持つ横磁場アイジングモデルのトロッター化進化について考察する：\n",
        "\n",
        "$$\n",
        "    H = \\sum_{\\langle i,j\\rangle}J_{ij}Z_iZ_j + \\sum_i h_i X_i\n",
        "$$\n",
        "\n",
        "時間発展 $e^{-iH\\tau}$ を実装するために、時間区間 $\\tau$ を $r$ のステップに分割し、 $\\Delta\\tau=\\tau/r$ と定義する。2次トロッター・鈴木分解により、以下の式が得られる：\n",
        "\n",
        "$$\n",
        "    e^{-iH\\Delta\\tau}\\approx \\prod_i e^{-ih_i X_i\\Delta\\tau/2 } \\prod_{\\langle i,j\\rangle} e^{-iJ_{ij}Z_iZ_j\\Delta\\tau} \\prod_i e^{-ih_iX_i\\Delta\\tau/2}\n",
        "$$\n",
        "\n",
        "回路の構築にあたっては、各トロッターステップが、単一量子ビットの $R_x$ 回転と、2量子ビットの $R_{ZZ}$ ゲートの連続として実装される。 この回路は、交互に配置された量子ビットに対してXゲートを適用し、ネール状態 $|0101\\cdots\\rangle$ を生成することから始まります。 その後の各トロッターステップでは、(1) すべての量子ビットに対して $R_x(h_i\\Delta\\tau)$ を適用し、(2) チェーン上の隣接するペアごとに $R_{ZZ}(2J_{ij}\\Delta\\tau)$ を適用し、(3) 再びすべての量子ビットに対して $R_x(h_i\\Delta\\tau)$ を適用する。 回路の総深さは、トロッターステップ数 $r$ に比例して増加する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "020f72af",
      "metadata": {},
      "source": [
        "<span id=\"requirements\" />\n",
        "\n",
        "## 要件\n",
        "\n",
        "なお、このチュートリアルでは、 macOS または Linux が必要です。 Qiskit.jl 現在、Windows ではサポートされていません（ [このオープンイシュー](https://github.com/Qiskit/Qiskit.jl/issues/15) で追跡されています）。\n",
        "\n",
        "まず、 [Juliaのダウンロードページ](https://julialang.org/downloads/)に記載されている手順に従って、Juliaをインストールしてください。 このチュートリアルはJulia（ 1.11 ）を使用して作成されました。以下のコマンドでインストールしてください `juliaup add 1.11`。\n",
        "\n",
        "次に、ターミナルで次のコマンドを実行して、Julia パッケージをグローバル環境 `IJulia` にインストールします。これにより、Jupyter ノートブック内で Julia を実行できるようになります。\n",
        "\n",
        "```\n",
        "julia -e 'using Pkg; Pkg.add(\"IJulia\")'\n",
        "```\n",
        "\n",
        "プロジェクト環境のセットアップには、Juliaの組み込みパッケージマネージャーを使用します。 環境を設定するには、2つの方法があります。\n",
        "\n",
        "*選択肢 1* ：一時的な環境。 以下のコードセルを実行すると、一時的な環境を設定し、必要なパッケージをインストールできます\n",
        "\n",
        "*選択肢 2* ：テストを行った環境を正確に再現する。 下のセルに `download_toml_files = true` 設定してください。 このセルは、 [ドキュメントリポジトリ ](https://github.com/Qiskit/documentation/tree/main/docs/tutorials/assets/time-evolution/julia)`Manifest.toml` から と `Project.toml` を、このノートブックの隣にある フォルダ `env_tutorial/time-evolution/` にダウンロードし、その環境を起動して、記録されているパッケージの正確なバージョンをインストールします。 プロジェクトファイルには、環境に関する概要が記述されています。例えば、 セクション `[deps]` にはすべての依存関係が列挙されています。 マニフェストファイルには、すべてのパッケージ（間接的な依存関係を含む）の正確なバージョンが指定されており、これにより環境を再現可能にしています。 詳細については、 [Juliaのドキュメント](https://pkgdocs.julialang.org/v1/toml-files/)を参照してください。\n",
        "\n",
        "以下の依存関係が環境にインストールされます。\n",
        "\n",
        "量子回路の構築および実行については：\n",
        "\n",
        "* `Qiskit.jl`\n",
        "* `QiskitIBMRuntime.jl`\n",
        "\n",
        "古典シミュレーションの場合：\n",
        "\n",
        "* `OrdinaryDiffEq.jl`\n",
        "* `TensorNetworkQuantumSimulator.jl`\n",
        "\n",
        "後処理の結果および可視化については：\n",
        "\n",
        "* `StatsBase.jl`\n",
        "* `Plots.jl`\n",
        "\n",
        "このチュートリアルは、 0.6.0 および `QiskitIBMRuntime.jl` 0.3.1 で `Qiskit.jl` 動作確認済みです。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "id": "1454cc50",
      "metadata": {},
      "outputs": [],
      "source": [
        "using Pkg\n",
        "using Downloads\n",
        "\n",
        "download_toml_files = false\n",
        "\n",
        "if !download_toml_files\n",
        "    # Option 1: Install the latest versions of the required packages into a temporary environment\n",
        "    Pkg.activate(mktempdir(); io=devnull)\n",
        "    Pkg.add([\n",
        "        PackageSpec(name=\"Qiskit\"),\n",
        "        PackageSpec(name=\"QiskitIBMRuntime\"),\n",
        "        PackageSpec(name=\"Python_jll\"),\n",
        "        PackageSpec(name=\"OrdinaryDiffEq\"),\n",
        "        PackageSpec(name=\"TensorNetworkQuantumSimulator\"),\n",
        "        PackageSpec(name=\"StatsBase\"),\n",
        "        PackageSpec(name=\"Plots\"),\n",
        "    ]; io=devnull)\n",
        "else\n",
        "    # Option 2: Install the exact tested versions pinned in the downloaded Project.toml and Manifest.toml\n",
        "    base_url = \"https://raw.githubusercontent.com/Qiskit/documentation/main/docs/tutorials/assets/time-evolution/julia\"\n",
        "    env_dir = joinpath(@__DIR__, \"env_tutorial\", \"time-evolution\")\n",
        "    mkpath(env_dir)\n",
        "    for file in (\"Project.toml\", \"Manifest.toml\")\n",
        "        Downloads.download(\"$base_url/$file\", joinpath(env_dir, file))\n",
        "    end\n",
        "\n",
        "    Pkg.activate(env_dir; io=devnull)\n",
        "    Pkg.instantiate(; io=devnull) # installs the exact versions recorded in Manifest.toml\n",
        "end"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a13bff0e",
      "metadata": {},
      "source": [
        "ここまでで、ノートブックを実行するためのJuliaプロジェクト環境をセットアップしました。 IBM の量子処理ユニットでワークフローを実行するには、 IBM Quantum アカウントとAPIトークンが必要です。これらを使用して、サービスインスタンスを作成します `qiskit-ibm-runtime`。 「 [ハードウェアで最初のサーキットを実行する](/docs/guides/hello-world) 」のトピックにある「インストールと認証」の手順に従って、APIトークンを生成し、インスタンス CRN を確認してください。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "613853a6",
      "metadata": {},
      "source": [
        "<span id=\"setup\" />\n",
        "\n",
        "## セットアップ\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "id": "4ea0efac",
      "metadata": {},
      "outputs": [],
      "source": [
        "using Qiskit\n",
        "using Qiskit.Operations\n",
        "using QiskitIBMRuntime\n",
        "using StatsBase\n",
        "using OrdinaryDiffEq\n",
        "using SparseArrays\n",
        "using LinearAlgebra\n",
        "using TensorNetworkQuantumSimulator\n",
        "using Plots: plot, plot!, heatmap, @layout, mm"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5016929d",
      "metadata": {},
      "source": [
        "また、ビット列の 位置 `v` にあるビットの値を返す、以下の効用関数を定義する `i`。 たとえば、( `v = 6` 2進数 `110`)の場合、\n",
        "\n",
        "* `bit_at(6, 1)` returns `0`,\n",
        "* `bit_at(6, 2)` returns `1`,\n",
        "* `bit_at(6, 3)` 戻ります `1`。\n",
        "\n",
        "これは、Qiskit で採用されている[リトルエンディアン方式](/docs/guides/bit-ordering)に従ったものです。つまり、位置のインデックス `i` は最下位ビット（「右端」のビット）から数えられます。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "id": "143aecbe",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "bit_at"
            ]
          },
          "execution_count": 21,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "\"\"\"\n",
        "    bit_at(v::Integer, i::Integer) = (v >> (i-1)) & 1\n",
        "\n",
        "Return the value of the bit at position `i` in `v`.\n",
        "\"\"\"\n",
        "bit_at(v::Integer, i::Integer) = (v >> (i-1)) & 1"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6a17088d",
      "metadata": {},
      "source": [
        "<span id=\"small-scale-simulator-example\" />\n",
        "\n",
        "## 小規模シミュレータの例\n",
        "\n",
        "上記の横磁場イジングモデルによって記述される、 $N$ 個の量子ビットからなる 1D 鎖について考察する。 対象とするシステムについて、以下にシステムサイズ `N`、トロッター法におけるステップサイズ `δt`、およびトロッター法の総ステップ数を指定する `r_max`。 総進化時間は です `δt * r_max`。 なお、Julia は Unicode 識別子をサポートしています。ノートブックや Julia REPL で `δt`; を入力するには、; の `\\delta` 後に Tab キーを押してください `δ`。 詳細については、 [JuliaのUnicode入力に関するドキュメント](https://docs.julialang.org/en/v1/manual/unicode-input/)を参照してください。\n",
        "\n",
        "<span id=\"exact-solution\" />\n",
        "\n",
        "### 厳密解\n",
        "\n",
        "量子ハードウェアによる結果を比較するための基準を確立するため、まず小規模な問題に対する古典的シミュレーションのワークフローを実証する。 イジング・ハミルトニアンを疎行列として構築し、次に、 `ODEProblem` からを用いてシュレーディンガー方程式を数値積分することで、正確な時間発展を求めます `OrdinaryDiffEq.jl`。 このアプローチは、量子ビット数 $N$ に比例して指数関数的に計算量が膨れ上がります。また、 $2^N$ 次元の状態ベクトル全体を保存する必要があります。 $N=20$ の場合、ヒルベルト空間の次元数はすでに100万を超えているため、より大規模なシステムには実用的ではありません。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "id": "aa6b4db3",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "1048576×1048576 SparseMatrixCSC{ComplexF64, Int64} with 22020096 stored entries:\n",
              "⎡⣿⣿⣾⢦⡀⠳⣄⠀⠀⠀⠳⣄⠀⠀⠀⠀⠀⠀⠀⠀⠳⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎤\n",
              "⎢⠺⣟⢻⣶⣿⡂⠈⠳⣄⠀⠀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎥\n",
              "⎢⢤⡈⠻⠻⠿⣧⣤⣠⡈⠳⠄⠀⠀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎥\n",
              "⎢⠀⠙⢦⡀⠀⣻⣿⣿⣙⣦⡀⠀⠀⠀⠀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎥\n",
              "⎢⠀⠀⠀⠙⢦⡈⠳⣼⣿⣿⡆⠀⠀⠀⠀⠀⠀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎥\n",
              "⎢⠙⢦⡀⠀⠀⠁⠀⠈⠈⠉⣿⣿⣾⢦⡀⠳⣄⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀⠀⎥\n",
              "⎢⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠺⣟⢻⣶⣿⡂⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠳⣄⠀⠀⠀⠀⠀⠀⎥\n",
              "⎢⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⢤⡈⠻⠻⠿⣧⣤⣠⡈⠳⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠳⣄⠀⠀⠀⠀⎥\n",
              "⎢⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠙⢦⡀⠀⣻⣿⣿⣙⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠳⣄⠀⠀⎥\n",
              "⎢⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠙⢦⡈⠳⣼⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠳⣄⎥\n",
              "⎢⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⡟⢦⡈⠳⣄⠀⠀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀⠀⎥\n",
              "⎢⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠻⣍⣿⣿⣯⠀⠈⠳⣄⠀⠀⠈⠳⣄⠀⠀⠀⠀⠀⠀⎥\n",
              "⎢⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢦⡈⠋⠛⢻⣶⣦⣦⡈⠓⠀⠀⠀⠈⠳⣄⠀⠀⠀⠀⎥\n",
              "⎢⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠨⣿⠿⣧⣽⡦⠀⠀⠀⠀⠀⠈⠳⣄⠀⠀⎥\n",
              "⎢⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡀⠀⠀⠙⢦⠈⠳⡿⣿⣿⣀⡀⡀⠀⢀⠀⠀⠈⠳⣄⎥\n",
              "⎢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠸⣿⣿⡟⢦⡈⠳⣄⠀⠀⠀⎥\n",
              "⎢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠈⠻⣍⣿⣿⣯⠀⠈⠳⣄⠀⎥\n",
              "⎢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠐⢦⡈⠋⠛⢻⣶⣦⣦⡈⠓⎥\n",
              "⎢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠙⢦⡀⠨⣿⠿⣧⣽⡦⎥\n",
              "⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⠀⠀⠀⠙⢦⠈⠳⡿⣿⣿⎦"
            ]
          },
          "execution_count": 22,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "N = 20\n",
        "δt = 0.05 # Trotter step size\n",
        "r_max = 10 # total number of Trotter steps\n",
        "\n",
        "h = fill(1.0, N)\n",
        "J = fill(1.0, N-1)\n",
        "\n",
        "# Build the Ising Hamiltonian as a sparse 2^n × 2^n matrix\n",
        "function build_ising_hamiltonian(h::AbstractVector{<:Real}, J::AbstractVector{<:Real}, n::Int)\n",
        "    dim = 2^n\n",
        "\n",
        "    # diagonal ZZ terms\n",
        "    diag_terms = zeros(Float64, dim)\n",
        "    for i in 1:n-1\n",
        "        for b in 0:dim-1\n",
        "            bi = bit_at(b, i) # bit at position i\n",
        "            bi_next = bit_at(b, i+1) # bit at position i + 1\n",
        "            diag_terms[b+1] += J[i] * (1-2bi) * (1-2bi_next)\n",
        "        end\n",
        "    end\n",
        "    H = spdiagm(0 => complex(diag_terms))\n",
        "\n",
        "    # off-diagonal local X terms\n",
        "    for i in 1:n\n",
        "        mask = 1 << (i-1)\n",
        "        cols = [xor(b, mask) + 1 for b in 0:dim-1]\n",
        "        H += h[i] * sparse(1:dim, cols, ones(ComplexF64, dim), dim, dim)\n",
        "    end\n",
        "    return H\n",
        "end\n",
        "\n",
        "H_ising = build_ising_hamiltonian(h, J, N)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bbe38420",
      "metadata": {},
      "source": [
        "シュレーディンガー方程式の右辺を、インプレース形式で定義する `schrodinger!(dψ, ψ, H, t)`。これは、疎行列とベクトルの乗算を用いて、 $d\\psi/dt = -iH\\psi$ を計算するものである。 次に、ネール状態を `ODEProblem` 初期条件として設定し、時間範囲 $[0, r \\cdot \\delta t]$ にわたって解き、各時間ステップ $\\delta t$ で状態を保存する。使用したソルバーは `Tsit5()`、非剛性問題に適した標準的な明示的4次・5次ルンゲ・クッタ法である。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "id": "959f77e9",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "retcode: Success\n",
              "Interpolation: 1st order linear\n",
              "t: 11-element Vector{Float64}:\n",
              " 0.0\n",
              " 0.05\n",
              " 0.1\n",
              " 0.15\n",
              " 0.2\n",
              " 0.25\n",
              " 0.3\n",
              " 0.35\n",
              " 0.4\n",
              " 0.45\n",
              " 0.5\n",
              "u: 11-element Vector{Vector{ComplexF64}}:\n",
              " [0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im  …  0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im]\n",
              " [-7.612535273941705e-14 + 2.5737401150886516e-29im, 7.616818423232204e-14 - 1.6944517510822304e-12im, -8.565903349044157e-17 + 3.2368190823993794e-15im, -7.61682079584434e-14 - 1.078515326911689e-15im, 1.523363843119942e-13 - 1.6912125988569567e-12im, 3.5867824743714624e-11 + 5.083352813839524e-12im, -7.608249752495255e-14 - 4.317561743447096e-15im, 7.616820798431766e-14 - 1.6944516451719627e-12im, -8.570258514925147e-17 + 3.2384113624188233e-15im, -7.606534127496737e-14 - 5.398093819616815e-15im  …  -7.591102113501652e-14 - 7.55501666902211e-15im, 1.5233640806402347e-13 - 1.691212597789024e-12im, -4.283149391646935e-17 + 3.2390475588024777e-15im, -7.61253567131055e-14 - 4.319154099332238e-15im, 1.28498500555455e-16 + 4.773388002812907e-18im, -8.570258413862945e-17 + 3.2384113624488572e-15im, -7.612534879063769e-14 - 3.2390464923709225e-15im, 1.5233638826330585e-13 - 1.6912127047672224e-12im, -4.283149290692347e-17 + 3.237455101084436e-15im, -7.612535273941595e-14 - 1.8338992189508272e-31im]\n",
              " [-8.680854672628291e-11 - 3.427254579020333e-25im, 8.709110140864061e-11 - 8.699033104505336e-10im, -5.649235901782656e-13 + 8.601572275260816e-12im, -8.709221846767839e-11 - 2.859732693854631e-12im, 1.7418295344900034e-10 - 8.612608133903897e-10im, 8.41248317362033e-9 + 2.6096671235273274e-9im, -8.652487588621059e-11 - 1.1500395899126693e-11im, 8.709222358844944e-11 - 8.699014655672987e-10im, -5.669821718119223e-13 + 8.629638578162805e-12im, -8.641073444337035e-11 - 1.4395664161950265e-11im  …  -8.538755211456945e-11 - 2.0113079067784756e-11im, 1.7418407565004836e-10 - 8.612606969068827e-10im, -2.825548799186401e-13 + 8.640787361594646e-12im, -8.680873675466659e-11 - 1.152847038256832e-11im, 8.478635815548866e-13 + 8.382372443494577e-14im, -5.669819735592012e-13 + 8.629638588149376e-12im, -8.680836165042751e-11 - 8.640671375786309e-12im, 1.7418313902498964e-10 - 8.61262658275938e-10im, -2.82554682353394e-13 + 8.612701741862262e-12im, -8.680854672628374e-11 - 2.811149115586865e-25im]\n",
              " [-4.2861942928308275e-9 - 4.7678984538985196e-24im, 4.318192995176613e-9 - 2.8269371315624182e-8im, -6.395173522788358e-11 + 6.447233357075582e-10im, -4.318468070877377e-9 - 2.1364257686596578e-10im, 8.636571975410676e-9 - 2.7617721500979347e-8im, 1.7289660717976908e-7 + 8.480086489483005e-8im, -4.253920910159066e-9 - 8.649865429907717e-10im, 4.318470318624579e-9 - 2.826906169988642e-8im, -6.446071076018044e-11 + 6.495016281145607e-10im, -4.240844230135151e-9 - 1.0846764703342651e-9im  …  -4.124170626784771e-9 - 1.5115818225612714e-9im, 8.636849310525618e-9 - 2.7617681592276622e-8im, -3.199878870600196e-11 + 6.513863923787342e-10im, -4.2862418335791054e-9 - 8.697676141630365e-10im, 9.60478168658149e-11 + 1.4206678132640617e-11im, -6.446062402203318e-11 + 6.495016332435747e-10im, -4.286148929585427e-9 - 6.513467397401749e-10im, 8.636617557977306e-9 - 2.7618031117900408e-8im, -3.1998702345812497e-11 + 6.466014984949206e-10im, -4.286194292830829e-9 + 4.870909626742163e-24im]\n",
              " [-6.079348924748445e-8 + 6.709717322272516e-24im, 6.162943323939352e-8 - 2.9592110353110093e-7im, -1.6696556398383817e-9 + 1.2400459826013194e-8im, -6.164292787255694e-8 - 4.088131560944853e-9im, 1.2326810978249792e-7 - 2.832733452226872e-7im, 1.253532043962043e-6 + 8.875042569125039e-7im, -5.994408800994472e-8 - 1.6725258647088304e-8im, 6.164314112979357e-8 - 2.9591021577421156e-7im, -1.6948387141108349e-9 + 1.2572865374243683e-8im, -5.959595610442699e-8 - 2.1031419496566967e-8im  …  -5.651357562833814e-8 - 2.9192023780832225e-8im, 1.2328181992163385e-7 - 2.832706038202527e-7im, -8.359520177503641e-10 + 1.2640019589288568e-8im, -6.079590106381668e-8 - 1.689785040734888e-8im, 2.5106376181130386e-9 + 5.084778396177926e-10im, -1.6948306165735295e-9 + 1.2572866042727832e-8im, -6.079128573701664e-8 - 1.2637312624047932e-8im, 1.2327033399936622e-7 - 2.8328423313378375e-7im, -8.359439919088748e-10 + 1.2467163914771088e-8im, -6.079348924748447e-8 + 1.0331673240130025e-23im]\n",
              " [-4.193552407608965e-7 - 1.840220498495959e-23im, 4.2862657866184504e-7 - 1.605297190776032e-6im, -1.8502762435969943e-8 + 1.0856276308591437e-7im, -4.288690355597115e-7 - 3.554458373697522e-8im, 8.574220964863143e-7 - 1.4932465582703908e-6im, 4.849187224415274e-6 + 4.812233679729101e-6im, -4.098425461298137e-7 - 1.4745065418194435e-7im, 4.288753395920834e-7 - 1.6051467128773302e-6im, -1.896035285782807e-8 + 1.1102835700521827e-7im, -4.0588320553359593e-7 - 1.8611022850670223e-7im  …  -3.711838427223188e-7 - 2.569391306045151e-7im, 8.57670971098675e-7 - 1.4931825847645462e-6im, -9.271568570757063e-9 + 1.1197289579952942e-7im, -4.194005371452928e-7 - 1.4992045110994755e-7im, 2.787088237718031e-8 + 7.194933454521717e-9im, -1.8960118645415406e-8 + 1.1102838165568638e-7im, -4.193161709409199e-7 - 1.1191024844294344e-7im, 8.574617742181924e-7 - 1.4933970418540967e-6im, -9.271337900947239e-9 + 1.0949690324053836e-7im, -4.193552407608964e-7 + 1.6524848989693985e-22im]\n",
              " [-1.7823579016922897e-6 - 1.087640585040274e-21im, 1.840838369770109e-6 - 5.569854913729441e-6im, -1.1658899308162594e-7 + 5.632670364049069e-7im, -1.843111911436975e-6 - 1.8277839588324167e-7im, 3.6832950716080163e-6 - 4.979757871286645e-6im, 1.1823232043972897e-5 + 1.668138856075027e-5im, -1.7216192586061922e-6 - 7.718155525067347e-7im, 1.8432004842500001e-6 - 5.56872697042903e-6im, -1.209408931510706e-7 + 5.825677201706816e-7im, -1.6958321412209815e-6 - 9.789484717969276e-7im  …  -1.4727630743780977e-6 - 1.3421173522554028e-6im, 3.6856596566327488e-6 - 4.9790105233659736e-6im, -5.848359517965976e-8 + 5.898080282235565e-7im, -1.7828068643880377e-6 - 7.911632992433939e-7im, 1.760517112427114e-7 + 5.557422909554899e-8im, -1.209376913040035e-7 + 5.825681268981909e-7im, -1.7819976541714096e-6 - 5.890838036292954e-7im, 3.6836637838442504e-6 - 4.980885908360778e-6im, -5.848046807781978e-8 + 5.703874412047737e-7im, -1.7823579016922876e-6 + 1.4997773495573015e-22im]\n",
              " [-5.2719847869895295e-6 + 8.772351797140282e-21im, 5.515796864069832e-6 - 1.3769890958036113e-5im, -4.854583030811284e-7 + 1.984102714841576e-6im, -5.52914007682216e-6 - 6.365426377065764e-7im, 1.1041341496086288e-5 - 1.1652942788167796e-5im, 1.9151485012220565e-5 + 4.1169949873337434e-5im, -5.0149560721693026e-6 - 2.748560607544284e-6im, 5.529875137426081e-6 - 1.3764484293927507e-5im, -5.114444270677655e-7 + 2.0817439894898367e-6im, -4.903067916522327e-6 - 3.508133202204623e-6im  …  -3.950715241692067e-6 - 4.767013437270117e-6im, 1.1055449702075777e-5 - 1.1647607717886785e-5im, -2.4383689790869913e-7 + 2.1174362562762014e-6im, -5.274804158840664e-6 - 2.846520575369006e-6im, 7.355815857851513e-7 + 2.7656731682993024e-7im, -5.114187341304747e-7 + 2.0817477909234415e-6im, -5.2699143882793144e-6 - 2.112332735357189e-6im, 1.1043481329588082e-5 - 1.1658350328429614e-5im, -2.438120770802614e-7 + 2.018953103020384e-6im, -5.271984786989539e-6 + 6.138686657683503e-21im]\n",
              " [-1.1617825704147756e-5 + 1.0312565819538484e-21im, 1.2349337633136464e-5 - 2.5744303624623147e-5im, -1.454293291805138e-6 + 5.123664098726546e-6im, -1.2403650700016836e-5 - 1.6202581807656819e-6im, 2.473960492472325e-5 - 2.0155561130978555e-5im, 1.9144096039811722e-5 + 7.6742969783544e-5im, -1.0832694804431494e-5 - 7.1930875309620025e-6im, 1.2407719644833958e-5 - 2.572612053989065e-5im, -1.56229208977908e-6 + 5.474515092672054e-6im, -1.0480130191816845e-5 - 9.254685626031852e-6im  …  -7.537537188446326e-6 - 1.2435206581306264e-5im, 2.4798220145598703e-5 - 2.0129513964044365e-5im, -7.316420138432232e-7 + 5.598791194770797e-6im, -1.1630271281791021e-5 - 7.545396775206743e-6im, 2.2142322134173096e-6 + 9.742099793903422e-7im, -1.5621555243617513e-6 + 5.474538012007301e-6im, -1.1609612670484607e-5 - 5.574263610620754e-6im, 2.4748196626943606e-5 - 2.0173749496261283e-5im, -7.315119289888009e-7 + 5.243914596674148e-6im, -1.1617825704147746e-5 + 2.0077178062353968e-21im]\n",
              " [-1.9812558848038747e-5 - 9.187798066332235e-22im, 2.147271081932555e-5 - 3.757217609507472e-5im, -3.2943974661872274e-6 + 1.0138423201098428e-5im, -2.163583224409355e-5 - 3.1479593611068202e-6im, 4.3072956212126986e-5 - 2.6216146005671797e-5im, 4.770433131249609e-6 + 0.00011143181451766211im, -1.7992013464296718e-5 - 1.4466566267165694e-5im, 2.1652013724844488e-5 - 3.752687773861608e-5im, -3.6269134427165884e-6 + 1.1086241359275966e-5im, -1.7142579310500252e-5 - 1.8804566182208357e-5im  …  -1.0216935244391546e-5 - 2.491043927093904e-5im, 4.325353440439837e-5 - 2.6122963951736878e-5im, -1.6606359562313976e-6 + 1.140941830342574e-5im, -1.9853711381944784e-5 - 1.541920404485947e-5im, 5.050007317756615e-6 + 2.569541043839736e-6im, -3.6263960453836696e-6 + 1.1086337766500889e-5im, -1.97886585017898e-5 - 1.1323323936752868e-5im, 4.309833408283902e-5 - 2.6261466566058982e-5im, -1.6601519712867477e-6 + 1.044756873253024e-5im, -1.981255884803875e-5 + 7.339651656276922e-20im]\n",
              " [-2.6605994524636198e-5 + 1.1289591858171765e-19im, 2.9532145628332138e-5 - 4.333877076489454e-5im, -5.793688435837011e-6 + 1.572023652812328e-5im, -2.9906819721527362e-5 - 4.767746092973603e-6im, 5.9370303731772103e-5 - 2.51584831603933e-5im, -2.1873141629015348e-5 + 0.00012741720406900944im, -2.3313208885217603e-5 - 2.288272975975095e-5im, 2.995521974547466e-5 - 4.325274969426522e-5im, -6.580507052690018e-6 + 1.770923159800008e-5im, -2.1702668886267368e-5 - 3.0142728729320425e-5im  …  -8.927183090969304e-6 - 3.921197964153728e-5im, 5.979856139686108e-5 - 2.4903653161242186e-5im, -2.9274853045629046e-6 + 1.8356702741523666e-5im, -2.6711940545518465e-5 - 2.488368314305582e-5im, 8.967724203429812e-6 + 5.238269352768273e-6im, -6.579046665900031e-6 + 1.770952822000892e-5im, -2.6553193423229552e-5 - 1.812661956307733e-5im, 5.942741740138485e-5 - 2.5244572524328294e-5im, -2.9261511036959703e-6 + 1.6330572728121542e-5im, -2.660599452463617e-5 - 3.440870688152987e-20im]"
            ]
          },
          "execution_count": 23,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# initial state |0101...01⟩\n",
        "ψ0 = zeros(ComplexF64, 2^N)\n",
        "neel_index = sum(1 << (i-1) for i in 1:2:N)\n",
        "ψ0[neel_index + 1] = 1.0\n",
        "\n",
        "function schrodinger!(dψ::AbstractVector, ψ::AbstractVector, H::AbstractMatrix, t::Real)\n",
        "    mul!(dψ, H, ψ)\n",
        "    dψ .*= -im\n",
        "end\n",
        "\n",
        "tspan = (0.0, r_max * δt)\n",
        "prob = ODEProblem(schrodinger!, ψ0, tspan, H_ising)\n",
        "sol = solve(prob, Tsit5(), saveat=δt)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8054932d",
      "metadata": {},
      "source": [
        "状態ベクトル $\\psi(t)$ を表す解から、サイトごとの磁化量を、単一量子ビット $\\langle Z\\rangle$ の期待値として、時間の関数として求めることができる。 これを、トロッター化回路から得られた結果と比較する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "id": "27b209db",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "11×20 Matrix{Float64}:\n",
              " -1.0       1.0       -1.0       1.0       …  1.0       -1.0       1.0\n",
              " -0.995021  0.995034  -0.995034  0.995034     0.995034  -0.995034  0.995021\n",
              " -0.980189  0.980386  -0.980386  0.980386     0.980386  -0.980386  0.980189\n",
              " -0.955994  0.956968  -0.956968  0.956968     0.956968  -0.956968  0.955994\n",
              " -0.922667  0.925652  -0.925653  0.925653     0.925653  -0.925652  0.922667\n",
              " -0.881106  0.888117  -0.88812   0.88812   …  0.88812   -0.888117  0.881106\n",
              " -0.832251  0.846116  -0.846129  0.846129     0.846129  -0.846116  0.832251\n",
              " -0.776957  0.801257  -0.801298  0.801298     0.801298  -0.801257  0.776957\n",
              " -0.715858  0.754749  -0.75486   0.75486      0.75486   -0.754749  0.715858\n",
              " -0.649744  0.707628  -0.707895  0.707895     0.707895  -0.707628  0.649744\n",
              " -0.580117  0.661272  -0.661841  0.661842  …  0.661841  -0.661272  0.580117"
            ]
          },
          "execution_count": 24,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# get a single-qubit expectation value ⟨Z_qubit⟩ from a full state vector, weighting ±1 by |amplitude|²\n",
        "function z_expval_from_state(ψ::AbstractVector{<:Complex}, qubit::Int, n::Int)\n",
        "    s = 0.0\n",
        "    for b in 0:2^n-1\n",
        "        bit = bit_at(b, qubit)\n",
        "        s += (1 - 2bit) * abs2(ψ[b+1])\n",
        "    end\n",
        "    return s\n",
        "end\n",
        "\n",
        "classical_magnetizations = [z_expval_from_state(sol.u[r+1], q, N)\n",
        "                             for r in 0:r_max, q in 1:N]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c3568ea2",
      "metadata": {},
      "source": [
        "<span id=\"small-scale-simulation-of-the-trotterized-circuits\" />\n",
        "\n",
        "### トロッター化回路の小規模シミュレーション\n",
        "\n",
        "以下では、当研究で提案したテンソルネットワーク手法を用いて、ノイズのない回路の古典的シミュレーション結果を示し `TensorNetworkQuantumSimulator.jl`、これにより、我々の回路構築手法の妥当性を検証する。 これらの手法は、量子ハードウェアによる結果と比較するための基準となる。\n",
        "\n",
        "まず、格子を、 1D の鎖グラフとして定義する `named_grid((N,))`。ここで、各頂点はタプルである `(i,)`。 次に、回路のゲートをタプルのリストとして指定します `(gate_name, qubit_indices, gate_parameter)`。これが、テンソルネットワークシミュレータの入力形式となります。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 25,
      "id": "47e7b661",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "make_trotter_circuit_tn (generic function with 1 method)"
            ]
          },
          "execution_count": 25,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# 1D chain graph — vertices are named (1,), (2,), ..., (N,)\n",
        "g = named_grid((N,))\n",
        "\n",
        "# Gates to prepare Néel state |0101…⟩, X on every other site\n",
        "neel_state_gates(n::Int) = [(\"X\", [(i,)]) for i in 1:2:n]\n",
        "\n",
        "# Gates for one second-order Trotter step of size δt\n",
        "trotter_step_gates(h::AbstractVector{<:Real}, J::AbstractVector{<:Real}, n::Int, δt::Real) = vcat(\n",
        "    [(\"Rx\",  [(i,)],         h[i] * δt) for i in 1:n],\n",
        "    [(\"Rzz\", [(i,), (i+1,)], 2 * J[i] * δt) for i in 1:n-1],\n",
        "    [(\"Rx\",  [(i,)],         h[i] * δt) for i in 1:n])\n",
        "\n",
        "# Make a list of gates: Néel state preparation followed by n_trotter_steps Trotter steps\n",
        "function make_trotter_circuit_tn(h::AbstractVector{<:Real}, J::AbstractVector{<:Real}, n::Int, δt::Real,\n",
        "                                 n_trotter_steps::Int)\n",
        "    circuit = []\n",
        "\n",
        "    # Neel state initialization\n",
        "    append!(circuit, neel_state_gates(n))\n",
        "\n",
        "    for _ in 1:n_trotter_steps\n",
        "        append!(circuit, trotter_step_gates(h, J, n, δt))\n",
        "    end\n",
        "\n",
        "    return circuit\n",
        "end"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2425014b",
      "metadata": {},
      "source": [
        "テンソルネットワークの収縮には、信念伝播アルゴリズムを用いています。 この手法は、エンタングルメントが限られている回路では効率的ですが、回路の深さとともにエンタングルメントが増加するにつれて、その精度は低下します。 および `maxdim` パラメータ `cutoff` は、精度と計算コストのバランスを調整します。 同様に、後で比較できるように、各サイトにおける磁化を計算する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 26,
      "id": "5e3ea2c3",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "fidelity at Trotter step 0 was 1.0\n",
            "fidelity at Trotter step 1 was 1.0\n",
            "fidelity at Trotter step 2 was 1.0\n",
            "fidelity at Trotter step 3 was 0.9999999999999679\n",
            "fidelity at Trotter step 4 was 0.9999999999976941\n",
            "fidelity at Trotter step 5 was 0.9999999999476229\n",
            "fidelity at Trotter step 6 was 0.9999999993741544\n",
            "fidelity at Trotter step 7 was 0.9999999993647009\n",
            "fidelity at Trotter step 8 was 0.9999999992323603\n",
            "fidelity at Trotter step 9 was 0.9999999980892764\n",
            "fidelity at Trotter step 10 was 0.9999999980892698\n"
          ]
        }
      ],
      "source": [
        "apply_kwargs = (; maxdim=32, cutoff=1e-10, normalize_tensors=true)\n",
        "tn_magnetizations = zeros(r_max+1, N)\n",
        "\n",
        "# |↑↑…↑⟩ product state, wrapped in a belief propagation cache\n",
        "tn_initial_state(g::NamedGraph) = BeliefPropagationCache(\n",
        "    tensornetworkstate(ComplexF32, v -> \"↑\", g, \"S=1/2\"))\n",
        "\n",
        "# Apply a gate list to a TN state; returns the evolved state and the\n",
        "# truncation fidelity, such as ∏(1 - ε) over all gate applications\n",
        "function apply_gates_to_tn_state(circuit::Vector, ψ_bpc::BeliefPropagationCache; apply_kwargs::NamedTuple)\n",
        "    ψ_bpc, errs = apply_gates(circuit, ψ_bpc; apply_kwargs)\n",
        "    return ψ_bpc, prod(1.0 .- errs)\n",
        "end\n",
        "\n",
        "# ⟨Z_q⟩ on every site of a tensor-network state\n",
        "z_expvals_from_tn_state(ψ_bpc::BeliefPropagationCache, n::Int) =\n",
        "    [real(expect(ψ_bpc, [(\"Z\", [(q,)])])[1]) for q in 1:n]\n",
        "\n",
        "for r in 0:r_max\n",
        "    circuit = make_trotter_circuit_tn(h, J, N, δt, r)\n",
        "    ψ_bpc, fidelity = apply_gates_to_tn_state(circuit, tn_initial_state(g); apply_kwargs)\n",
        "    println(\"fidelity at Trotter step $(r) was $(fidelity)\")\n",
        "    tn_magnetizations[r+1, :] = z_expvals_from_tn_state(ψ_bpc, N)\n",
        "end"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "aeb0878b",
      "metadata": {},
      "source": [
        "<span id=\"step-1-map-classical-inputs-to-a-quantum-problem\" />\n",
        "\n",
        "### ステップ1：古典的な入力を量子問題に写像する\n",
        "\n",
        "ここで、を用いてトロッター化された時間発展回路を構築する `Qiskit.jl`。 この回路はテンソルネットワーク版を反映したもので、ネール状態を初期化し、 $R_x$ および $R_{ZZ}$ ゲートを用いた $r$ 回のトロッターステップを適用し、最後にすべての量子ビットをZ基底で測定する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "id": "6b680069",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "QuantumCircuit with 20 qubits, 20 clbits\n",
              "  instructions: 89"
            ]
          },
          "execution_count": 27,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "function make_trotter_circuit(h::AbstractVector{<:Real}, J::AbstractVector{<:Real}, n::Int, δt::Real, n_trotter_steps::Int)\n",
        "    qc = QuantumCircuit(n, n)\n",
        "\n",
        "    # Neel state initialization\n",
        "    for i in 1:2:n\n",
        "        x!(qc, i)\n",
        "    end\n",
        "\n",
        "    # Trotter evolution\n",
        "    for _ in 1:n_trotter_steps\n",
        "        for i in 1:n\n",
        "            rx!(qc, h[i] * δt, i)\n",
        "        end\n",
        "\n",
        "        for i in 1:n-1\n",
        "            rzz!(qc, 2* J[i] * δt, i, i+1)\n",
        "        end\n",
        "\n",
        "        for i in 1:n\n",
        "            rx!(qc, h[i] * δt, i)\n",
        "        end\n",
        "    end\n",
        "\n",
        "    # measure in Z basis\n",
        "    for i in 1:n\n",
        "        measure!(qc, i, i)\n",
        "    end\n",
        "    return qc\n",
        "end\n",
        "\n",
        "\n",
        "qc = make_trotter_circuit(h, J, N, δt, 1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7a7e4d8f",
      "metadata": {},
      "source": [
        "進化時間 $\\tau = 0, \\delta t, 2\\delta t, \\ldots, 10\\delta t$ に対応する、トロッターのステップ0から10までの回路のリストを作成する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 28,
      "id": "704485a7",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "11-element Vector{QuantumCircuit}:\n",
              " QuantumCircuit(20, 20; 30 instructions)\n",
              " QuantumCircuit(20, 20; 89 instructions)\n",
              " QuantumCircuit(20, 20; 148 instructions)\n",
              " QuantumCircuit(20, 20; 207 instructions)\n",
              " QuantumCircuit(20, 20; 266 instructions)\n",
              " QuantumCircuit(20, 20; 325 instructions)\n",
              " QuantumCircuit(20, 20; 384 instructions)\n",
              " QuantumCircuit(20, 20; 443 instructions)\n",
              " QuantumCircuit(20, 20; 502 instructions)\n",
              " QuantumCircuit(20, 20; 561 instructions)\n",
              " QuantumCircuit(20, 20; 620 instructions)"
            ]
          },
          "execution_count": 28,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# prepare a list of circuits with different Trotter steps\n",
        "qc_list = [make_trotter_circuit(h, J, N, δt, r) for r in 0:r_max]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3b7100d9",
      "metadata": {},
      "source": [
        "<span id=\"step-2-optimize-problem-for-quantum-hardware-execution\" />\n",
        "\n",
        "### ステップ 2：量子ハードウェアでの実行に向けて問題を最適化する\n",
        "\n",
        "量子ハードウェア上で実行するには、まず回路をトランスパイルする必要があります。 これには、以下の手順が含まれます。回路をマッピングする物理量子ビットのセットを選択し、ゲートをバックエンドのネイティブ命令セットに再コンパイルし、その結果得られる回路の深さを最適化することです。 を使用して、利用可能なバックエンドのうち最も負荷の低いものを自動的に選択 `least_busy()` し、を使用してそのネイティブゲートセットと量子ビットの接続情報を取得 `target_from_backend()` し、を使用してコンパイルを実行 `transpile()` します。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a63ecabe",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "backend.name = \"ibm_phoenix\"\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "\"ibm_phoenix\""
            ]
          },
          "execution_count": 95,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "service = Service()\n",
        "search_results = backend_search(service)\n",
        "backend = least_busy(search_results)\n",
        "@show backend.name"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 37,
      "id": "14205fe7",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "Target with 120 qubits\n",
              "  instructions: 8"
            ]
          },
          "execution_count": 37,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "target = target_from_backend(backend, service)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 38,
      "id": "8828900e",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "11-element Vector{QuantumCircuit}:\n",
              " QuantumCircuit(120, 20; 30 instructions)\n",
              " QuantumCircuit(120, 20; 211 instructions)\n",
              " QuantumCircuit(120, 20; 344 instructions)\n",
              " QuantumCircuit(120, 20; 475 instructions)\n",
              " QuantumCircuit(120, 20; 606 instructions)\n",
              " QuantumCircuit(120, 20; 737 instructions)\n",
              " QuantumCircuit(120, 20; 868 instructions)\n",
              " QuantumCircuit(120, 20; 999 instructions)\n",
              " QuantumCircuit(120, 20; 1130 instructions)\n",
              " QuantumCircuit(120, 20; 1261 instructions)\n",
              " QuantumCircuit(120, 20; 1392 instructions)"
            ]
          },
          "execution_count": 38,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "tqc_list = [transpile(qc, target)[1] for qc in qc_list]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "501e8dc5",
      "metadata": {},
      "source": [
        "トランスパイレーションの後、コンパイルされた回路の2つの特性を検証します。 `get_circuit_layout()` その回路に対して選択された物理量子ビットのインデックスの集合を返します。 `two_qubit_depth()` 2量子ビットゲートの深さ（回路内の2量子ビット演算からなる最長の連鎖の長さ）を計算する。これは、ハードウェアにおけるノイズの蓄積を示す有用な指標となる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 39,
      "id": "bf4c910c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "Set{Int64} with 20 elements:\n",
              "  35\n",
              "  110\n",
              "  58\n",
              "  12\n",
              "  24\n",
              "  37\n",
              "  23\n",
              "  22\n",
              "  47\n",
              "  69\n",
              "  36\n",
              "  80\n",
              "  109\n",
              "  90\n",
              "  57\n",
              "  34\n",
              "  13\n",
              "  59\n",
              "  70\n",
              "  100"
            ]
          },
          "execution_count": 39,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "function get_circuit_layout(tqc::QuantumCircuit)\n",
        "    return Set(q for inst in tqc.data for q in inst.qubits)\n",
        "end\n",
        "\n",
        "get_circuit_layout(tqc_list[2])"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1f5318ec",
      "metadata": {},
      "source": [
        "以下に、各トロッターステップにおける2量子ビットゲートの数と回路の深さを示す。予想通り、どちらもステップ数に比例して線形に増加している。 なお、小数点 $R_\\mathrm{ZZ}$ ゲートは、現時点ではC APIからは利用できません（ [qiskit-ibm-runtime-c#29](https://github.com/Qiskit/qiskit-ibm-runtime-c/issues/29) を参照）。 その結果、それぞれが1つの2量子ビットゲートではなく2つの2量子ビットゲートにトランスパイルされる `RZZGate` ため、2量子ビットゲートの使用数が膨れ上がってしまう。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 40,
      "id": "5fa03372",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "r=0: 2q gate count=0, 2q gate depth=0\n",
            "r=1: 2q gate count=38, 2q gate depth=38\n",
            "r=2: 2q gate count=76, 2q gate depth=42\n",
            "r=3: 2q gate count=114, 2q gate depth=46\n",
            "r=4: 2q gate count=152, 2q gate depth=50\n",
            "r=5: 2q gate count=190, 2q gate depth=54\n",
            "r=6: 2q gate count=228, 2q gate depth=58\n",
            "r=7: 2q gate count=266, 2q gate depth=62\n",
            "r=8: 2q gate count=304, 2q gate depth=66\n",
            "r=9: 2q gate count=342, 2q gate depth=70\n",
            "r=10: 2q gate count=380, 2q gate depth=74\n"
          ]
        }
      ],
      "source": [
        "two_qubit_count(qc::QuantumCircuit) = count(inst -> length(inst.qubits) == 2, qc.data)\n",
        "\n",
        "function two_qubit_depth(qc::QuantumCircuit)\n",
        "    qubit_depth = Dict{Int,Int}()\n",
        "    for inst in qc.data\n",
        "        length(inst.qubits) == 2 || continue   # skip non-two-qubit gates\n",
        "        d = maximum(get(qubit_depth, q, 0) for q in inst.qubits)\n",
        "        for q in inst.qubits\n",
        "            qubit_depth[q] = d + 1\n",
        "        end\n",
        "    end\n",
        "    return isempty(qubit_depth) ? 0 : maximum(values(qubit_depth))\n",
        "end\n",
        "\n",
        "for (i, tqc) in enumerate(tqc_list)\n",
        "    println(\"r=$(i-1): 2q gate count=$(two_qubit_count(tqc)), 2q gate depth=$(two_qubit_depth(tqc))\")\n",
        "end"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "37aabbc8",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute-using-qiskit-primitives\" />\n",
        "\n",
        "### ステップ 3: `Qiskit primitives` を使用して実行する\n",
        "\n",
        "これで、トランスパイルされた回路を、指定 `shots` された条件付きで `Sampler` ジョブとしてバックエンドに送信できるようになりました。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 41,
      "id": "7bcdead5",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "11-element Vector{QiskitIBMRuntime.Job}:\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x00000003427f72f0)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x00000004b2d1b4e0)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x00000004b2dcb180)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x00000004b1e24840)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x00000004b266e640)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x00000004b2d1b690)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000104c17980)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x00000004b315b9b0)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000104c16090)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000104c195f0)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x00000004b2d33f70)"
            ]
          },
          "execution_count": 41,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "shots = 1024\n",
        "job_list = [run_sampler_job(service, backend, tqc, shots) for tqc in tqc_list]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 46,
      "id": "9bca942a",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Job 1: Completed\n",
            "Job 2: Completed\n",
            "Job 3: Completed\n",
            "Job 4: Completed\n",
            "Job 5: Completed\n",
            "Job 6: Completed\n",
            "Job 7: Completed\n",
            "Job 8: Completed\n",
            "Job 9: Completed\n",
            "Job 10: Completed\n",
            "Job 11: Completed\n"
          ]
        }
      ],
      "source": [
        "for (i, job) in enumerate(job_list)\n",
        "    status = get_job_status(job, service)\n",
        "    println(\"Job $i: \", status)\n",
        "end"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f1429d09",
      "metadata": {},
      "source": [
        "ジョブが完了すると、その結果を取得することができます。 なお、この関 `get_sampler_job_results` 数は、ジョブが完了するまでブロックされます。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 47,
      "id": "e8f81320",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "11-element Vector{QiskitIBMRuntime.Samples}:\n",
              " [[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]  …  [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]]\n",
              " [[1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]  …  [1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]]\n",
              " [[1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0]  …  [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]]\n",
              " [[1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1], [1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]  …  [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1], [1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]]\n",
              " [[1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0], [1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]  …  [1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]]\n",
              " [[1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0], [1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0], [1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0], [1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]  …  [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1], [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1], [1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1], [1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0], [0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]]\n",
              " [[0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0], [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0], [1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]  …  [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0], [0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1], [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]]\n",
              " [[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0], [1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0], [1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1], [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1], [0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0], [0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0]  …  [1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1], [0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0], [0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0], [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]]\n",
              " [[0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1], [0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0], [1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0], [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]  …  [1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0], [0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0], [1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0]]\n",
              " [[0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0], [1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0], [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1], [0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0], [0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0], [0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1], [1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1], [0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0]  …  [1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0], [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0], [1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1]]\n",
              " [[1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0]  …  [1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0], [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0], [1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0], [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0], [1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0]]"
            ]
          },
          "execution_count": 47,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "all_samples = [get_sampler_job_results(job, service) for job in job_list]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "64b46f68",
      "metadata": {},
      "source": [
        "<span id=\"step-4-post-process-and-return-result-in-desired-classical-format\" />\n",
        "\n",
        "### ステップ4：後処理を行い、結果を指定された従来の形式で出力する\n",
        "\n",
        "量子ハードウェアから得られたビットストリングのサンプルから、すべてのショットについて $(-1)^{b_i}$ を平均化することで、サイトごとの磁化（単一量子ビットの $\\langle Z\\rangle$ の期待値）を計算する。ここで、 $b_i$ は量子ビット $i$ の測定されたビットである。次に、量子ビットおよびトロッターステップごとに磁化をヒートマップとしてプロットし、3つの手法（厳密な古典シミュレーション、ノイズのないテンソルネットワークシミュレーション、およびハードウェア実行）を並べて比較する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 48,
      "id": "e7ee3928",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "11×20 Matrix{Float64}:\n",
              " -0.996094  0.998047  -0.990234  0.998047  …  1.0       -0.988281  0.994141\n",
              " -0.925781  0.980469  -0.878906  0.96875      0.970703  -0.976562  0.988281\n",
              " -0.916016  0.992188  -0.837891  0.957031     0.962891  -0.966797  0.953125\n",
              " -0.884766  0.970703  -0.824219  0.90625      0.908203  -0.939453  0.892578\n",
              " -0.835938  0.96875   -0.814453  0.884766     0.931641  -0.902344  0.908203\n",
              " -0.777344  0.958984  -0.78125   0.871094  …  0.935547  -0.876953  0.939453\n",
              " -0.732422  0.933594  -0.767578  0.8125       0.884766  -0.835938  0.890625\n",
              " -0.650391  0.916016  -0.771484  0.771484     0.853516  -0.773438  0.837891\n",
              " -0.537109  0.902344  -0.705078  0.742188     0.875     -0.662109  0.833984\n",
              " -0.472656  0.923828  -0.652344  0.728516     0.839844  -0.695312  0.808594\n",
              " -0.4375    0.923828  -0.613281  0.681641  …  0.890625  -0.658203  0.8125"
            ]
          },
          "execution_count": 48,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Compute expectation values\n",
        "# 0 -> 1, 1 -> -1\n",
        "z_expval(samples, i) = mean((-1)^s[i] for s in samples)\n",
        "\n",
        "magnetizations = [z_expval(all_samples[i], q) for i in 1:length(all_samples), q in 1:N]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a1b2c3d4",
      "metadata": {},
      "source": [
        "以下の3つの図は、サイト磁化 $\\langle Z_i \\rangle$ を、量子ビットのインデックス（x軸）およびトロッターステップ（y軸）の関数として示したものである。 $\\delta t = 0.05$、 $r_{\\max} = 10$ の場合、総進化時間は $\\tau = r_{\\max} \\cdot \\delta t = 0.5$ となり、これは初期の反強磁性パターンがまだ減衰していないほど十分に短い時間であるため、3つの手法すべてで強く交互に現れるパターンが観察される。 古典ネットワークとテンソルネットワークの結果は現在、ほぼ一致しており、このステップサイズではトロッター誤差が小さいことが確認された。 ハードウェアの結果は、おおむね他の2つと一致しているが、一部の量子ビットは他の量子ビットよりもシミュレーション結果から大きく外れており、これはバックエンド全体における量子ビットの品質にばらつきがあることを反映している。 回路の深さが増すにつれて、これらの偏差は、後のトロッター法の手順において大きくなっていく。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 49,
      "id": "cc5496cc",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/time-evolution/extracted-outputs/cc5496cc-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 49,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# plot magnetization as a function of time\n",
        "l = @layout [a{0.3w} b{0.3w} c{0.44w}]\n",
        "plot(\n",
        "    heatmap(classical_magnetizations, title=\"Classical\", clims=(-1,1), color=:RdBu,\n",
        "        xlabel=\"Qubit\", ylabel=\"Trotter steps\", colorbar=false),\n",
        "    heatmap(tn_magnetizations, title=\"Tensor Network\", clims=(-1,1), color=:RdBu,\n",
        "        xlabel=\"Qubit\", ylabel=\"Trotter steps\", colorbar=false),\n",
        "    heatmap(magnetizations, title=\"Hardware\", clims=(-1,1), color=:RdBu,\n",
        "        xlabel=\"Qubit\", ylabel=\"Trotter steps\", colorbar=true),\n",
        "    layout=l, size=(900,300),\n",
        "    bottom_margin=5mm, left_margin=5mm, right_margin=6mm\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5e9fc890",
      "metadata": {},
      "source": [
        "<span id=\"large-scale-hardware-example\" />\n",
        "\n",
        "## 大規模なハードウェアの例\n",
        "\n",
        "<span id=\"steps-1–4-in-a-single-workflow\" />\n",
        "\n",
        "### 1～4の手順を1つのワークフローで実行\n",
        "\n",
        "ここでは、上記の4つのステップすべてを1つのワークフローに統合し、従来の厳密なシミュレーションでは到達できない規模で処理を行います。 磁化をサイトごとに解く代わりに、反強磁性秩序を表す単一のスカラー量、すなわちスタッガード磁化を追跡する：\n",
        "\n",
        "$$\n",
        "    \\langle M_s \\rangle = \\frac{1}{N} \\sum_{i=1}^{N} (-1)^i \\langle Z_i \\rangle\n",
        "$$\n",
        "\n",
        "和の式における符号の交替によって、信号が可視化される。 ネール初期状態 $|0101\\ldots01\\rangle$ では、すべての項が $+1$ を寄与するため、 $\\langle M_s\\rangle = 1$ となる。一方、単純な平均 $\\frac{1}{N}\\sum_i \\langle Z_i\\rangle$ は、すべての $t$ に対して恒等的にゼロとなる。横磁場が交互のパターンを乱すため、 $\\langle M_s\\rangle$ は $0$ に向かって減衰し、したがって、スタッガード磁化は、時間発展の過程で初期の秩序がどれだけ残存するかを示している。\n",
        "\n",
        "また、この例を用いて、トロッターのステップサイズが精度にどのような影響を与えるかを確認します。 総進化時間 $T = 1.5$ を固定し、トロッターステップ数 $r \\in \\{3, 6, 12\\}$ を変化させる。この際、 $\\delta t = T/r$ となるようにする。ハードウェア上では、2つの誤差要因が競合する。すなわち、 $\\delta t$ を小さくするとトロッター誤差は減少するが、それに比例して2量子ビットゲートの使用数が増加し、その結果、ハードウェアノイズが蓄積される。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 50,
      "id": "f840b38f",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "  δt = 0.5  →  4 time points, deepest circuit = 3 Trotter steps, 2q count = 594, 2q depth = 206\n",
            "  δt = 0.25  →  7 time points, deepest circuit = 6 Trotter steps, 2q count = 1188, 2q depth = 218\n",
            "  δt = 0.125  →  13 time points, deepest circuit = 12 Trotter steps, 2q count = 2376, 2q depth = 242\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "24-element Vector{QiskitIBMRuntime.Job}:\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000104c1a750)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000102e0a270)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000104c21a50)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000102e05120)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000104c2a6e0)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000102e0d140)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000102e0b640)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000104c1a200)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x00000004b312eb90)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000104c22060)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x00000004b31ea4e0)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000104c1ccf0)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000104c2af50)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x00000004b312ffb0)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x00000004b0e89700)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000102e15070)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000102e10d40)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x00000004af5a5d10)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000102e12500)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000102e14870)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000102e10730)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x00000004b237ca60)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x00000004b2c713a0)\n",
              " QiskitIBMRuntime.Job(Ptr{QiskitIBMRuntime.LibQiskitIBMRuntime.Job} @0x0000000102e13e90)"
            ]
          },
          "execution_count": 50,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# -------------------------Step 1-------------------------\n",
        "# Map classical inputs to a quantum problem.\n",
        "N_large = 100\n",
        "g_large = named_grid((N_large,))\n",
        "h_large = fill(1.0, N_large)       # transverse field on every site\n",
        "J_large = fill(1.0, N_large - 1)   # nearest-neighbor ZZ couplings on the chain\n",
        "\n",
        "T_total = 1.5                    # fixed total evolution time\n",
        "r_list = [3, 6, 12]       # varying Trotter steps; δt = T_total/r\n",
        "sweep = [(r, k) for r in r_list for k in 0:r]\n",
        "\n",
        "qc_list_large = [make_trotter_circuit(h_large, J_large, N_large, T_total/r, k)\n",
        "                 for (r, k) in sweep]\n",
        "\n",
        "# -------------------------Step 2-------------------------\n",
        "# Optimize the problem for quantum hardware execution.\n",
        "tqc_list_large = [transpile(qc, target)[1] for qc in qc_list_large]\n",
        "# Print the 2q gate count and depth of the deepest circuit at each δt\",\n",
        "for r in r_list\n",
        "    i = findfirst(==((r, r)), sweep)   # the k = r circuit reaches the full T_total\n",
        "    println(\"  δt = $(round(T_total/r, digits=4))  →  $(r+1) time points, \",\n",
        "        \"deepest circuit = $(r) Trotter steps, \",\n",
        "        \"2q count = $(two_qubit_count(tqc_list_large[i])), \",\n",
        "        \"2q depth = $(two_qubit_depth(tqc_list_large[i]))\")\n",
        "end\n",
        "\n",
        "# -------------------------Step 3-------------------------\n",
        "# Execute using Qiskit primitives.\n",
        "shots_large = 4096\n",
        "\n",
        "job_list_large = [run_sampler_job(service, backend, tqc, shots_large)\n",
        "                  for tqc in tqc_list_large]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 53,
      "id": "10004db8",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Job 1 (δt=0.5, k=0): Completed\n",
            "Job 2 (δt=0.5, k=1): Completed\n",
            "Job 3 (δt=0.5, k=2): Completed\n",
            "Job 4 (δt=0.5, k=3): Completed\n",
            "Job 5 (δt=0.25, k=0): Completed\n",
            "Job 6 (δt=0.25, k=1): Completed\n",
            "Job 7 (δt=0.25, k=2): Completed\n",
            "Job 8 (δt=0.25, k=3): Completed\n",
            "Job 9 (δt=0.25, k=4): Completed\n",
            "Job 10 (δt=0.25, k=5): Completed\n",
            "Job 11 (δt=0.25, k=6): Completed\n",
            "Job 12 (δt=0.125, k=0): Completed\n",
            "Job 13 (δt=0.125, k=1): Completed\n",
            "Job 14 (δt=0.125, k=2): Completed\n",
            "Job 15 (δt=0.125, k=3): Completed\n",
            "Job 16 (δt=0.125, k=4): Completed\n",
            "Job 17 (δt=0.125, k=5): Completed\n",
            "Job 18 (δt=0.125, k=6): Completed\n",
            "Job 19 (δt=0.125, k=7): Completed\n",
            "Job 20 (δt=0.125, k=8): Completed\n",
            "Job 21 (δt=0.125, k=9): Completed\n",
            "Job 22 (δt=0.125, k=10): Completed\n",
            "Job 23 (δt=0.125, k=11): Completed\n",
            "Job 24 (δt=0.125, k=12): Completed\n"
          ]
        }
      ],
      "source": [
        "# Run this cell to check the job status\n",
        "# Run the following cell for post-processing after all jobs complete\n",
        "for (i, job) in enumerate(job_list_large)\n",
        "    r, k = sweep[i]\n",
        "    println(\"Job $i (δt=$(round(T_total/r, digits=4)), k=$k): \",\n",
        "            get_job_status(job, service))\n",
        "end"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 54,
      "id": "a3646d14",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "24-element Vector{Float64}:\n",
              " 0.9880371093750097\n",
              " 0.697231445312484\n",
              " 0.44886718750000276\n",
              " 0.29333496093750067\n",
              " 0.9882324218750095\n",
              " 0.8109619140625324\n",
              " 0.6457958984374791\n",
              " 0.4808593749999992\n",
              " 0.36695312500000055\n",
              " 0.2963671875000012\n",
              " 0.23831542968750055\n",
              " 0.9884472656250093\n",
              " 0.8566455078125492\n",
              " 0.7951171875000282\n",
              " 0.7050732421874865\n",
              " 0.610673828124981\n",
              " 0.529980468749995\n",
              " 0.4656054687500018\n",
              " 0.4149316406250024\n",
              " 0.3799462890625011\n",
              " 0.35178710937500185\n",
              " 0.3185888671875003\n",
              " 0.31287597656250016\n",
              " 0.29621093750000077"
            ]
          },
          "execution_count": 54,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# -------------------------Step 4-------------------------\n",
        "# Post-process and return the result in the desired classical format.\n",
        "# Run this cell after all jobs are completed\n",
        "\n",
        "# ⟨M_s⟩ = (1/N) Σ (-1)^i ⟨Z_i⟩, averaged over hardware shots\n",
        "function staggered_magnetization(samples::AbstractVector{<:AbstractVector}, n::Int)\n",
        "    s = 0.0\n",
        "    for sample in samples\n",
        "        s += sum((-1)^i * (1 - 2 * sample[i]) for i in 1:n) / n\n",
        "    end\n",
        "    return s / length(samples)\n",
        "end\n",
        "\n",
        "all_samples_large = [get_sampler_job_results(job, service) for job in job_list_large]\n",
        "mags_hardware = [staggered_magnetization(s, N_large) for s in all_samples_large]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "89c310c8",
      "metadata": {},
      "source": [
        "$N=100$ では、上記で使用した常微分方程式ソルバーによる厳密解を求めることは不可能です。なぜなら、状態ベクトルだけでも $2^{100} \\approx 10^{30}$ 個の振幅が必要となるからです。 その代わりに、参照として、同じ 1D チェーンに対し、はるかに細かいトロッターステップを用いたノイズのないテンソルネットワークシミュレーション（ $r = 96$, $\\delta t \\approx 0.016$ ）を用いている。このシミュレーションでは、ハードウェア上で実行した $\\delta t$ と比較して、トロッター誤差は無視できるほど小さい。 この参照値自体も概算値であり、その主な誤差は、前述した債券次元の切り捨てによるもので、各実行ごとに「切り捨て精度」として報告されています。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 55,
      "id": "fbcc23a1",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Tensor-network reference:\n",
            "  δt=0.01562, 96 steps: truncation fidelity ≈ 1.0\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "([0.0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0, 1.125, 1.25, 1.375, 1.5], Float32[1.0, 0.9695576, 0.8870231, 0.77430177, 0.6560442, 0.5499543, 0.46285573, 0.39298016, 0.33518773, 0.28527063, 0.24147007, 0.20369667, 0.17206171])"
            ]
          },
          "execution_count": 55,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "apply_kwargs = (; maxdim=64, cutoff=1e-10, normalize_tensors=true)\n",
        "\n",
        "# Calculate the staggered magnetization given a tensor network state\n",
        "staggered_magnetization(ψ_bpc::BeliefPropagationCache, n::Int) =\n",
        "    sum((-1)^q * m for (q, m) in enumerate(z_expvals_from_tn_state(ψ_bpc, n))) / n\n",
        "\n",
        "# Evolve a TN state and record the staggered magnetization at each step.\n",
        "function compute_staggered_magnetization_tn(δt::Real, nsteps::Int; record_every::Int = 1)\n",
        "    init_gates = neel_state_gates(N_large)\n",
        "    step_gates = trotter_step_gates(h_large, J_large, N_large, δt)\n",
        "\n",
        "    ψ_bpc, fid = apply_gates_to_tn_state(init_gates, tn_initial_state(g_large); apply_kwargs)\n",
        "    times = [0.0]\n",
        "    mags = [staggered_magnetization(ψ_bpc, N_large)]\n",
        "    for k in 1:nsteps\n",
        "        ψ_bpc, fid_step = apply_gates_to_tn_state(step_gates, ψ_bpc; apply_kwargs)\n",
        "        fid *= fid_step\n",
        "        if k % record_every == 0\n",
        "            push!(times, k * δt)\n",
        "            push!(mags, staggered_magnetization(ψ_bpc, N_large))\n",
        "        end\n",
        "    end\n",
        "    println(\"  δt=$(round(δt, digits=5)), $(nsteps) steps: truncation fidelity ≈ $(round(fid, digits=5))\")\n",
        "    (times, mags)\n",
        "end\n",
        "\n",
        "# If the fidelity drifts from 1, raise `maxdim` in `apply_kwargs`.\n",
        "# Under current setting, the tensor network simulation takes ~ 3 minutes on a laptop.\n",
        "println(\"Tensor-network reference:\")\n",
        "r_ref = 96\n",
        "times_ref, mags_ref = compute_staggered_magnetization_tn(T_total / r_ref, r_ref; record_every = r_ref ÷ 12)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "af333ad4",
      "metadata": {},
      "source": [
        "以下のグラフは、3つのトロッターステップサイズにおける経時的なずれた磁化を、ノイズのないテンソルネットワークの参照値（黒の破線）と比較して示したものである。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 56,
      "id": "94cd122e",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/time-evolution/extracted-outputs/94cd122e-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 56,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "plt = plot(xlabel = \"Time\", ylabel = \"Staggered magnetization\",\n",
        "    title = \"N = $(N_large) on $(backend.name), T = $(T_total)\",\n",
        "    legend = :topright, ylims = (-0.05, 1.05), size = (820, 480),\n",
        "    bottom_margin = 5mm, left_margin = 5mm)\n",
        "\n",
        "# Plot tensor network reference\n",
        "plot!(plt, times_ref, mags_ref, lw = 2, ls = :dash, color = :black,\n",
        "      label = \"tensor network, δt → 0\")\n",
        "\n",
        "# Plot hardware result per Trotter step size\n",
        "for (r, stop) in zip(r_list, cumsum(r_list .+ 1))\n",
        "    plot!(plt, range(0, T_total, length = r + 1), mags_hardware[(stop - r):stop],\n",
        "          marker = :circle, markersize = 4, lw = 2,\n",
        "          label = \"hardware, δt = $(round(T_total / r, digits = 4))\")\n",
        "end\n",
        "plt"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "603fd062",
      "metadata": {},
      "source": [
        "全体として、最も粗いトロッターステップ $\\delta t = 0.5$ （オレンジ色の点）は、テンソルネットワークの基準値からの偏差が最も大きく、おそらくトロッター誤差の寄与が大きいと考えられる。 より細かいステップ（ $\\delta t = 0.25$、緑色の点）では、ハードウェアによる結果が基準値とより密接に一致しています。 最小のステップサイズ $\\delta t = 0.125$ （紫色の点）では、トロッター誤差は最小となるが、 $\\delta t = 0.25$ の場合よりも一致度は劣る。ステップサイズを半分にすると、各時点において必要な2量子ビットゲートの数が2倍になり、追加されるノイズがトロッター誤差の低減効果を上回ってしまう。 したがって、ハードウェア上のトロッター化回路において $\\delta t$ を選択することは、トロッター誤差と追加のゲートから生じるノイズの蓄積との間のトレードオフとなる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8defe5bb",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## 次のステップ\n",
        "\n",
        "以下の資料もご参考になるかもしれません：\n",
        "\n",
        "* [トロッター誤差を低減するための多製品対応の計算式](/docs/tutorials/multi-product-formula)\n",
        "\n",
        "* [量子コンピューティングと高性能コンピューティングの統合コース](/learning/courses/integrating-quantum-and-high-performance-computing)\n",
        "\n",
        "* [Qiskit.jl](https://github.com/Qiskit/Qiskit.jl) および [QiskitIBMRuntime.jl](https://github.com/Qiskit/QiskitIBMRuntime.jl) （ GitHub ）\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Julia 1.11",
      "language": "julia",
      "name": "julia-1.11"
    },
    "language_info": {
      "file_extension": ".jl",
      "mimetype": "application/julia",
      "name": "julia",
      "version": "1.11.5"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}