{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "dd701ecc",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"時間発展回路のための近似量子コンパイル\"\n",
        "description: \"AQC-Tensor を使用して、量子ハードウェア上で効率的に実行できるよう、トロッター化された時間発展回路を圧縮する方法を学びましょう。\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore circo Néel */}\n",
        "\n",
        "<span id=\"approximate-quantum-compilation-for-time-evolution-circuits\" />\n",
        "\n",
        "# 時間発展回路のための近似量子コンパイル\n",
        "\n",
        "*推定実行時間：Heronプロセッサで15秒（注：これはあくまで推定値です。 （実行時間は環境によって異なる場合があります。）*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "12608301",
      "metadata": {},
      "source": [
        "<span id=\"learning-outcomes\" />\n",
        "\n",
        "## 学習成果\n",
        "\n",
        "このチュートリアルを修了すると、以下の内容を理解できるようになります：\n",
        "\n",
        "* AQC-Tensor Qiskit アドオンを使用して、深層トロッター回路を浅層アンザッツ回路に圧縮する方法\n",
        "* トロッター回路からパラメータ化されたアンザッツを生成し、テンソルネットワーク（MPS）法を用いてそのパラメータを最適化する方法\n",
        "* 圧縮回路の目標進化に対する忠実度を評価し、量子ハードウェア上で実行する方法\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c3c5992a",
      "metadata": {},
      "source": [
        "<span id=\"prerequisites\" />\n",
        "\n",
        "## 前提条件\n",
        "\n",
        "以下のトピックについて、あらかじめ確認しておくことをお勧めします：\n",
        "\n",
        "* [量子回路の基礎](/learning/courses/basics-of-quantum-information)\n",
        "* [ハミルトニアンシミュレーションとトロッター化](/learning/courses/utility-scale-quantum-computing/quantum-simulation)\n",
        "* [プリミティブの紹介](/docs/guides/primitives)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "714adc39",
      "metadata": {},
      "source": [
        "<span id=\"background\" />\n",
        "\n",
        "## 背景\n",
        "\n",
        "このチュートリアルでは、Qiskit を使用してテンソルネットワーク（AQC-Tensor） **による近似量子コンパイル**を実装し、量子回路の性能を向上させる方法について解説します。 AQC-Tensorは、シミュレーションの精度を維持しつつ、深層のトロッター回路をより浅く、ハードウェアに適した回路に圧縮します。\n",
        "\n",
        "<span id=\"how-aqc-tensor-works\" />\n",
        "\n",
        "### AQC-Tensorの仕組み\n",
        "\n",
        "ハミルトニアン $H$ を、 $k$ 回のトロッター法ステップを用いて、総時間 $t$ かけてシミュレーションすることを考える。 トロッター回路の全容は以下の通りです：\n",
        "\n",
        "$$\n",
        "U_{\\text{full}} = \\left[U_{\\text{Trotter}}(t/k)\\right]^k\n",
        "$$\n",
        "\n",
        "単純なアプローチでは、回路の深さを扱いやすい範囲に抑えるためにトロッター法の手順数を少なくしますが、これにより大きなトロッター誤差が生じます。 AQC-Tensorは、精度と深さを分離することで、この矛盾を解決します：\n",
        "\n",
        "1. **対象回路（高精度、深層）：** 同じ進化時間に対して、多くのステップ（例えば、 $10k$ ）を持つトロッター回路を構築する。 この回路はトロッター誤差がはるかに少ないが、ハードウェアには深すぎる。 これは古典的には行列積状態（MPS）としてのみシミュレートされるため、深さは問題にならない。\n",
        "\n",
        "2. **アンザッツ回路（低次元、パラメータ化）：** 単一ステップのトロッター回路と同じ構造を持つパラメータ化回路 $V(\\theta)$ を定義する。 $V(\\theta_{\\text{init}}) = U_{\\text{Trotter}}(t/k)$ となるように初期化し、その後、 $\\theta$ を反復的に最適化して、 $V(\\theta)$ が高精度な目標状態を可能な限り忠実に再現するようにする。\n",
        "\n",
        "その結果、単一のトロッターステップの深さを維持しつつ、多数のステップに匹敵する精度を実現する回路が得られ、これにより、近い将来の量子ハードウェアへの実装が可能となった。\n",
        "\n",
        "<span id=\"when-to-use-aqc-tensor\" />\n",
        "\n",
        "### AQC-Tensorの使用タイミング\n",
        "\n",
        "AQC-Tensorは、次のような場合に最も効果を発揮します：\n",
        "\n",
        "* **回路の深さがハードウェアのコヒーレンス時間を超えている。** Trotterシミュレーションに必要なTrotterステップ数がデバイスの対応可能数を超える場合、AQC-Tensorはその展開を、より浅い回路に圧縮することができます。\n",
        "* **エンタングルメントは、古典力学の枠組み内で解くことが可能である。** 時間発展状態における総エンタングルメントは、主に発展時間 $t$ に依存し、トロッターステップ数 $k$ には依存しない。これは、 $t$ が十分に短く、結合の次元が扱いやすい範囲内に収まる限り、 $10k$ ステップを持つターゲット回路をMPSとして表現する難しさは、 $k$ ステップを持つ回路と概して変わらないことを意味する。\n",
        "* **自然なアプローチが存在する。** このアプローチはトロッター回路の構造を反映しているため、明確に定義された初期パラメータを備えた物理的に妥当な出発点を提供し、任意の変分アプローチに見られる収束の問題を回避することができる。\n",
        "\n",
        "このアプローチは、一般的な回路圧縮とは対照的です。AQC-Tensorは、任意のユニタリー演算を少ないゲート数で近似しようとするのではなく、同じゲート構造を維持したまま、そのパラメータを最適化することでトロッター誤差を低減します。 詳細については[、AQC-Tensorのドキュメント](https://qiskit.github.io/qiskit-addon-aqc-tensor/)を参照してください。\n",
        "\n",
        "このチュートリアルでは、ハミルトニアンの定義、トロッター回路の生成、テンソルネットワーク最適化による回路の圧縮、そして IBM Quantum® ハードウェア上での実行に至るまで、AQC-Tensorのワークフロー全体を順を追って解説します。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f8a05291",
      "metadata": {},
      "source": [
        "<span id=\"requirements\" />\n",
        "\n",
        "## 要件\n",
        "\n",
        "このチュートリアルを始める前に、以下のものがインストールされていることを確認してください：\n",
        "\n",
        "* Qiskit SDK v2.0 またはそれ以降、 [可視化](/docs/api/qiskit/visualization)機能をサポートしたもの\n",
        "* Qiskit Runtime v0.22 またはそれ以降 (`pip install qiskit-ibm-runtime`)\n",
        "* AQC-Tensor Qiskit アドオン (`pip install 'qiskit-addon-aqc-tensor[aer,quimb-jax]'`)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f9410d21",
      "metadata": {},
      "source": [
        "<span id=\"setup\" />\n",
        "\n",
        "## セットアップ\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "ecdb92e0",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "import quimb.tensor\n",
        "import datetime\n",
        "import matplotlib.pyplot as plt\n",
        "\n",
        "from scipy.linalg import expm\n",
        "from scipy.optimize import OptimizeResult, minimize\n",
        "\n",
        "from qiskit.quantum_info import SparsePauliOp, Pauli\n",
        "from qiskit.transpiler import CouplingMap\n",
        "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
        "from qiskit import QuantumCircuit\n",
        "from qiskit.synthesis import SuzukiTrotter\n",
        "\n",
        "from qiskit_addon_utils.problem_generators import (\n",
        "    generate_time_evolution_circuit,\n",
        ")\n",
        "from qiskit_addon_aqc_tensor.ansatz_generation import (\n",
        "    generate_ansatz_from_circuit,\n",
        ")\n",
        "from qiskit_addon_aqc_tensor.objective import MaximizeStateFidelity\n",
        "from qiskit_addon_aqc_tensor.simulation.quimb import QuimbSimulator\n",
        "from qiskit_addon_aqc_tensor.simulation import tensornetwork_from_circuit\n",
        "from qiskit_addon_aqc_tensor.simulation import compute_overlap\n",
        "\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "from qiskit_ibm_runtime import EstimatorV2 as Estimator\n",
        "from qiskit_ibm_runtime.fake_provider import FakeKyiv\n",
        "\n",
        "from rustworkx.visualization import graphviz_draw"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6473f943",
      "metadata": {},
      "source": [
        "<span id=\"small-scale-simulator-example\" />\n",
        "\n",
        "## 小規模シミュレータの例\n",
        "\n",
        "このセクションでは、10サイトシステムを用いて、AQC-Tensorのワークフローを段階的に解説します。 我々は、スピン相互作用や磁気的性質を調べるために広く研究されているモデルである、10サイトXXZスピン鎖のダイナミクスをシミュレーションする。\n",
        "\n",
        "ハミルトニアンは以下の通りです：\n",
        "\n",
        "$$\n",
        "\\hat{\\mathcal{H}}_{XXZ} = \\sum_{i=1}^{L-1} J_{i,(i+1)}\\left(X_i X_{(i+1)}+Y_i Y_{(i+1)}+ 2\\cdot Z_i Z_{(i+1)} \\right) \\, ,\n",
        "$$\n",
        "\n",
        "ここで、 $J_{i,(i+1)}$ は、辺 $(i, i+1)$ および $L=10$ に対するランダムな係数である。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6520161e",
      "metadata": {},
      "source": [
        "<span id=\"step-1-map-classical-inputs-to-a-quantum-problem\" />\n",
        "\n",
        "### ステップ1：古典的な入力を量子問題にマッピングする\n",
        "\n",
        "このステップでは、次のことを行います：\n",
        "\n",
        "1. ハミルトニアン、観測量、および初期状態を定義せよ。\n",
        "2. 後で比較できるように、古典的な方法で正確な期待値を計算してください。\n",
        "3. AQC-Tensor を使用して、高精度なトロッター回路（AQCのターゲット）を生成し、それを深さの浅いアンザッツに圧縮する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bbeb5729",
      "metadata": {},
      "source": [
        "<span id=\"set-up-the-hamiltonian-observable-and-initial-state\" />\n",
        "\n",
        "#### ハミルトニアン、観測量、および初期状態を設定する\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "527dbada",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Hamiltonian: SparsePauliOp(['IIIIIIIIII', 'IIIIIIIIXX', 'IIIIIIIIYY', 'IIIIIIIIZZ', 'IIIIIIXXII', 'IIIIIIYYII', 'IIIIIIZZII', 'IIIIXXIIII', 'IIIIYYIIII', 'IIIIZZIIII', 'IIXXIIIIII', 'IIYYIIIIII', 'IIZZIIIIII', 'XXIIIIIIII', 'YYIIIIIIII', 'ZZIIIIIIII', 'IIIIIIIXXI', 'IIIIIIIYYI', 'IIIIIIIZZI', 'IIIIIXXIII', 'IIIIIYYIII', 'IIIIIZZIII', 'IIIXXIIIII', 'IIIYYIIIII', 'IIIZZIIIII', 'IXXIIIIIII', 'IYYIIIIIII', 'IZZIIIIIII'],\n",
            "              coeffs=[1.        +0.j, 0.52440675+0.j, 0.52440675+0.j, 1.0488135 +0.j,\n",
            " 0.60759468+0.j, 0.60759468+0.j, 1.21518937+0.j, 0.55138169+0.j,\n",
            " 0.55138169+0.j, 1.10276338+0.j, 0.52244159+0.j, 0.52244159+0.j,\n",
            " 1.04488318+0.j, 0.4618274 +0.j, 0.4618274 +0.j, 0.9236548 +0.j,\n",
            " 0.57294706+0.j, 0.57294706+0.j, 1.14589411+0.j, 0.46879361+0.j,\n",
            " 0.46879361+0.j, 0.93758721+0.j, 0.6958865 +0.j, 0.6958865 +0.j,\n",
            " 1.391773  +0.j, 0.73183138+0.j, 0.73183138+0.j, 1.46366276+0.j])\n",
            "Observable: SparsePauliOp(['IIIIZZIIII'],\n",
            "              coeffs=[1.+0.j])\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/527dbada-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# L is the number of sites in the 1D spin chain\n",
        "L = 10\n",
        "\n",
        "# Generate the coupling map\n",
        "edge_list = [(i - 1, i) for i in range(1, L)]\n",
        "even_edges = edge_list[::2]\n",
        "odd_edges = edge_list[1::2]\n",
        "coupling_map = CouplingMap(edge_list)\n",
        "\n",
        "# Generate random coefficients for our XXZ Hamiltonian\n",
        "np.random.seed(0)\n",
        "Js = np.random.rand(L - 1) + 0.5 * np.ones(L - 1)\n",
        "hamiltonian = SparsePauliOp(Pauli(\"I\" * L))\n",
        "for i, edge in enumerate(even_edges + odd_edges):\n",
        "    hamiltonian += SparsePauliOp.from_sparse_list(\n",
        "        [\n",
        "            (\"XX\", (edge), Js[i] / 2),\n",
        "            (\"YY\", (edge), Js[i] / 2),\n",
        "            (\"ZZ\", (edge), Js[i]),\n",
        "        ],\n",
        "        num_qubits=L,\n",
        "    )\n",
        "\n",
        "# Generate a ZZ observable between the two middle qubits\n",
        "observable = SparsePauliOp.from_sparse_list(\n",
        "    [(\"ZZ\", (L // 2 - 1, L // 2), 1.0)], num_qubits=L\n",
        ")\n",
        "\n",
        "# Generate an initial Néel state |1010101010⟩\n",
        "initial_state_circuit = QuantumCircuit(L)\n",
        "for i in range(L):\n",
        "    if i % 2:\n",
        "        initial_state_circuit.x(i)\n",
        "\n",
        "print(\"Hamiltonian:\", hamiltonian)\n",
        "print(\"Observable:\", observable)\n",
        "graphviz_draw(coupling_map.graph, method=\"circo\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "54ad6963",
      "metadata": {},
      "source": [
        "<span id=\"compute-the-exact-expectation-value\" />\n",
        "\n",
        "#### 正確な期待値を計算する\n",
        "\n",
        "この規模のシステムについては、行列の指数関数演算を用いて、時間発展後の期待値を直接正確に求めることができる。 これは、AQC回路の精度を評価するための基準データとなります。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "20c70651",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "AQC evolution time: 0.2\n",
            "Subsequent evolution time: 0.066667\n",
            "Total evolution time: 0.266667\n",
            "Exact expectation value: -0.700899\n"
          ]
        }
      ],
      "source": [
        "aqc_evolution_time = 0.2\n",
        "\n",
        "# Each baseline Trotter step covers dt = aqc_evolution_time / 3\n",
        "# The subsequent (uncompressed) step covers 1 additional dt\n",
        "subsequent_evolution_time = aqc_evolution_time / 3\n",
        "total_evolution_time = aqc_evolution_time + subsequent_evolution_time\n",
        "\n",
        "# Compute exact expectation value via matrix exponentiation\n",
        "H_matrix = hamiltonian.to_matrix()\n",
        "U_exact = expm(-1j * H_matrix * total_evolution_time)\n",
        "\n",
        "# Build the initial state vector (Néel state)\n",
        "initial_state_vec = np.zeros(2**L)\n",
        "state_idx = sum(2**i for i in range(L) if i % 2)\n",
        "initial_state_vec[state_idx] = 1.0\n",
        "\n",
        "# Evolve and compute expectation value\n",
        "evolved_state = U_exact @ initial_state_vec\n",
        "obs_matrix = observable.to_matrix()\n",
        "exact_expval = (evolved_state.conj() @ obs_matrix @ evolved_state).real\n",
        "\n",
        "print(f\"AQC evolution time: {aqc_evolution_time}\")\n",
        "print(f\"Subsequent evolution time: {subsequent_evolution_time:.6f}\")\n",
        "print(f\"Total evolution time: {total_evolution_time:.6f}\")\n",
        "print(f\"Exact expectation value: {exact_expval:.6f}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a93c047c",
      "metadata": {},
      "source": [
        "<span id=\"generate-the-aqc-target-circuit\" />\n",
        "\n",
        "#### AQCターゲット回路を生成する\n",
        "\n",
        "ここで、AQCのターゲットとなるトロッター回路を構築する。 この回路は、高精度を実現するために多数のトロッター段階（32段階）を採用しています。 これはMPSとして古典的にシミュレートされるだけであり、ハードウェア上で実行されるわけではないため、深さが大きくても問題にはなりません。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "db66bf00",
      "metadata": {},
      "outputs": [],
      "source": [
        "aqc_target_num_trotter_steps = 32\n",
        "\n",
        "aqc_target_circuit = initial_state_circuit.copy()\n",
        "aqc_target_circuit.compose(\n",
        "    generate_time_evolution_circuit(\n",
        "        hamiltonian,\n",
        "        synthesis=SuzukiTrotter(reps=aqc_target_num_trotter_steps),\n",
        "        time=aqc_evolution_time,\n",
        "    ),\n",
        "    inplace=True,\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bce1ef52",
      "metadata": {},
      "source": [
        "<span id=\"generate-an-ansatz-initial-parameters-subsequent-circuit-and-a-baseline-circuit\" />\n",
        "\n",
        "#### 仮説、初期パラメータ、後続の回路、およびベースライン回路を生成する\n",
        "\n",
        "次に、AQCのターゲットと同じ進化時間を持つが、トロッターステップの数がはるかに少ない（たった1ステップのみ）「優れた」回路を構築する。 `generate_ansatz_from_circuit`この回路を に渡すと、次のように返されます：\n",
        "\n",
        "1. 同じ2量子ビット接続を持つ、一般的なパラメータ化された**アンザッツ**回路。\n",
        "2. ansatzに接続した際に入力回路を再現する**初期パラメータ**。\n",
        "\n",
        "また、以下も構築します：\n",
        "\n",
        "* [AQC-Tensorの初期状態チュートリアル](https://qiskit.github.io/qiskit-addon-aqc-tensor/tutorials/01_initial_state_aqc.html)で示された手法に従い、AQC最適化された部分の後に（非圧縮状態で）追加される、1つのトロッターステップを含む**後続の回路**。\n",
        "* 全実行時間（`aqc_evolution_time + subsequent_evolution_time`）にわたって4つのトロッターステップを使用する**ベースラインのトロッター回路**。これは比較対象として機能し、AQCを使用しないハードウェア上で実行される場合の状態を表しています。 AQCアプローチ（圧縮ステップ3回＋非圧縮ステップ1回）は、より浅い深さでも高い精度を実現する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "78f2665e",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Target circuit:      depth 384\n",
            "Baseline circuit:    depth 48 (4 Trotter steps, time=0.2667)\n",
            "Subsequent circuit:  depth 12 (1 Trotter step, time=0.0667)\n",
            "Ansatz circuit:      depth 3, with 156 parameters\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/78f2665e-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "aqc_ansatz_num_trotter_steps = 1\n",
        "\n",
        "aqc_good_circuit = initial_state_circuit.copy()\n",
        "aqc_good_circuit.compose(\n",
        "    generate_time_evolution_circuit(\n",
        "        hamiltonian,\n",
        "        synthesis=SuzukiTrotter(reps=aqc_ansatz_num_trotter_steps),\n",
        "        time=aqc_evolution_time,\n",
        "    ),\n",
        "    inplace=True,\n",
        ")\n",
        "\n",
        "aqc_ansatz, aqc_initial_parameters = generate_ansatz_from_circuit(\n",
        "    aqc_good_circuit\n",
        ")\n",
        "\n",
        "# Subsequent circuit: 1 non-compressed Trotter step appended after AQC\n",
        "subsequent_num_trotter_steps = 1\n",
        "subsequent_circuit = generate_time_evolution_circuit(\n",
        "    hamiltonian,\n",
        "    synthesis=SuzukiTrotter(reps=subsequent_num_trotter_steps),\n",
        "    time=subsequent_evolution_time,\n",
        ")\n",
        "\n",
        "# Baseline Trotter circuit: 4 Trotter steps over total evolution time, no AQC\n",
        "baseline_num_trotter_steps = 4\n",
        "baseline_circuit = initial_state_circuit.copy()\n",
        "baseline_circuit.compose(\n",
        "    generate_time_evolution_circuit(\n",
        "        hamiltonian,\n",
        "        synthesis=SuzukiTrotter(reps=baseline_num_trotter_steps),\n",
        "        time=total_evolution_time,\n",
        "    ),\n",
        "    inplace=True,\n",
        ")\n",
        "\n",
        "print(\n",
        "    f\"Target circuit:      depth {aqc_target_circuit.depth(lambda x: x.operation.num_qubits == 2)}\"\n",
        ")\n",
        "print(\n",
        "    f\"Baseline circuit:    depth {baseline_circuit.depth(lambda x: x.operation.num_qubits == 2)} ({baseline_num_trotter_steps} Trotter steps, time={total_evolution_time:.4f})\"\n",
        ")\n",
        "print(\n",
        "    f\"Subsequent circuit:  depth {subsequent_circuit.depth(lambda x: x.operation.num_qubits == 2)} ({subsequent_num_trotter_steps} Trotter step, time={subsequent_evolution_time:.4f})\"\n",
        ")\n",
        "print(\n",
        "    f\"Ansatz circuit:      depth {aqc_ansatz.depth(lambda x: x.operation.num_qubits == 2)}, with {len(aqc_initial_parameters)} parameters\"\n",
        ")\n",
        "aqc_ansatz.draw(\"mpl\", fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "be1b4049",
      "metadata": {},
      "source": [
        "<span id=\"set-up-tensor-network-simulation-and-build-the-target-mps\" />\n",
        "\n",
        "#### テンソルネットワークシミュレーションを設定し、対象のMPSを構築する\n",
        "\n",
        "我々は、 [quimb](https://github.com/jcmgray/quimb) 行列積状態（MPS）回路シミュレータを使用しており、勾配法による最適化にはJAXによる自動微分機能を活用しています。 次に、目標状態のMPS表現を構築し、初期アンザッツと目標状態との間の初期フィデリティを評価する。 問題のインスタンスは比較的小さな例であるため、初期の忠実度はかなり高い水準から始まります。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "666fcf42",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Target MPS maximum bond dimension: 5\n",
            "Starting fidelity: 0.998246\n"
          ]
        }
      ],
      "source": [
        "simulator_settings = QuimbSimulator(\n",
        "    quimb.tensor.CircuitMPS, autodiff_backend=\"jax\"\n",
        ")\n",
        "\n",
        "aqc_target_mps = tensornetwork_from_circuit(\n",
        "    aqc_target_circuit, simulator_settings\n",
        ")\n",
        "print(\"Target MPS maximum bond dimension:\", aqc_target_mps.psi.max_bond())\n",
        "\n",
        "good_mps = tensornetwork_from_circuit(aqc_good_circuit, simulator_settings)\n",
        "starting_fidelity = abs(compute_overlap(good_mps, aqc_target_mps)) ** 2\n",
        "print(f\"Starting fidelity: {starting_fidelity:.6f}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1f14eb3f",
      "metadata": {},
      "source": [
        "<span id=\"optimize-the-ansatz-parameters\" />\n",
        "\n",
        "#### 初期条件パラメータを最適化する\n",
        "\n",
        "L-BFGS-B最適化アルゴリズムを用いて、目的関数を `MaximizeStateFidelity` 最小化する。 オプティマイザは、仮説回路と目標MPSとの一致度を最大化するよう、仮説パラメータを反復的に調整する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "6ad144d6",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "2026-05-18 13:14:49.731596 Intermediate result: Fidelity 0.99952882\n",
            "2026-05-18 13:14:49.734425 Intermediate result: Fidelity 0.99958531\n",
            "2026-05-18 13:14:49.737101 Intermediate result: Fidelity 0.99960093\n",
            "2026-05-18 13:14:49.739813 Intermediate result: Fidelity 0.99961046\n",
            "2026-05-18 13:14:49.742969 Intermediate result: Fidelity 0.99962560\n",
            "2026-05-18 13:14:49.745916 Intermediate result: Fidelity 0.99964395\n",
            "2026-05-18 13:14:49.748615 Intermediate result: Fidelity 0.99968150\n",
            "2026-05-18 13:14:49.753684 Intermediate result: Fidelity 0.99970569\n",
            "2026-05-18 13:14:49.756208 Intermediate result: Fidelity 0.99973788\n",
            "2026-05-18 13:14:49.759067 Intermediate result: Fidelity 0.99975385\n",
            "2026-05-18 13:14:49.762321 Intermediate result: Fidelity 0.99976458\n",
            "2026-05-18 13:14:49.765526 Intermediate result: Fidelity 0.99977661\n",
            "2026-05-18 13:14:49.768496 Intermediate result: Fidelity 0.99978663\n",
            "2026-05-18 13:14:49.771278 Intermediate result: Fidelity 0.99980236\n",
            "2026-05-18 13:14:49.773735 Intermediate result: Fidelity 0.99981607\n",
            "2026-05-18 13:14:49.776339 Intermediate result: Fidelity 0.99982811\n",
            "2026-05-18 13:14:49.779177 Intermediate result: Fidelity 0.99985827\n",
            "2026-05-18 13:14:49.782243 Intermediate result: Fidelity 0.99988354\n",
            "2026-05-18 13:14:49.784904 Intermediate result: Fidelity 0.99991608\n",
            "2026-05-18 13:14:49.787737 Intermediate result: Fidelity 0.99993336\n",
            "2026-05-18 13:14:49.790414 Intermediate result: Fidelity 0.99993956\n",
            "2026-05-18 13:14:49.793029 Intermediate result: Fidelity 0.99994421\n",
            "2026-05-18 13:14:49.795585 Intermediate result: Fidelity 0.99994743\n",
            "2026-05-18 13:14:49.835045 Intermediate result: Fidelity 0.99994791\n",
            "2026-05-18 13:14:49.839786 Intermediate result: Fidelity 0.99994803\n",
            "2026-05-18 13:14:49.842403 Intermediate result: Fidelity 0.99994898\n",
            "2026-05-18 13:14:49.873779 Intermediate result: Fidelity 0.99994898\n",
            "Done after 27 iterations.\n"
          ]
        }
      ],
      "source": [
        "aqc_stopping_fidelity = 1\n",
        "aqc_max_iterations = 500\n",
        "\n",
        "stopping_point = 1.0 - aqc_stopping_fidelity\n",
        "objective = MaximizeStateFidelity(\n",
        "    aqc_target_mps, aqc_ansatz, simulator_settings\n",
        ")\n",
        "\n",
        "\n",
        "def callback(intermediate_result: OptimizeResult):\n",
        "    fidelity = 1 - intermediate_result.fun\n",
        "    print(\n",
        "        f\"{datetime.datetime.now()} Intermediate result: Fidelity {fidelity:.8f}\"\n",
        "    )\n",
        "    if intermediate_result.fun < stopping_point:\n",
        "        raise StopIteration\n",
        "\n",
        "\n",
        "result = minimize(\n",
        "    objective,\n",
        "    aqc_initial_parameters,\n",
        "    method=\"L-BFGS-B\",\n",
        "    jac=True,\n",
        "    options={\"maxiter\": aqc_max_iterations},\n",
        "    callback=callback,\n",
        ")\n",
        "if result.status not in (0, 1, 99):\n",
        "    raise RuntimeError(\n",
        "        f\"Optimization failed: {result.message} (status={result.status})\"\n",
        "    )\n",
        "\n",
        "print(f\"Done after {result.nit} iterations.\")\n",
        "aqc_final_parameters = result.x"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ea5b484a",
      "metadata": {},
      "source": [
        "<span id=\"assemble-the-final-aqc-circuit\" />\n",
        "\n",
        "#### 最終的なAQC回路を組み立てる\n",
        "\n",
        "最適化されたパラメータが得られたら、それらを仮説に結びつけ、続いて（圧縮されていない）トロッター法の手順を適用する。 この回路は、圧縮されたトロッターステップ1つ分と、圧縮されていないステップ1つ分の深さを持つが、圧縮された部分は32トロッターステップ分の精度に近似している。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "e09e40de",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/e09e40de-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "aqc_final_circuit = aqc_ansatz.assign_parameters(aqc_final_parameters)\n",
        "aqc_final_circuit.compose(subsequent_circuit, inplace=True)\n",
        "aqc_final_circuit.draw(\"mpl\", fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "047511db",
      "metadata": {},
      "source": [
        "<span id=\"step-2-optimize-problem-for-quantum-hardware-execution\" />\n",
        "\n",
        "### ステップ2：量子ハードウェア実行に向けた問題の最適化\n",
        "\n",
        "この小規模な例では、ローカルでハードウェアの実行をシミュレートするために、擬似バックエンド (`FakeKyiv`) を使用します。 AQC最適化回路（`aqc_final_circuit`）とベースラインのトロッター回路（`baseline_circuit`、全進化時間における4回のトロッターステップ、AQCなし）の両方を、バックエンドの命令セットアーキテクチャ（ISA）にトランスパイルし、回路の深さをさらに削減するために を用いる `optimization_level=3` 。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "9e7556dd",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "AQC circuit depth: 15\n",
            "Baseline Trotter circuit depth: 27\n"
          ]
        }
      ],
      "source": [
        "backend = FakeKyiv()\n",
        "\n",
        "pass_manager = generate_preset_pass_manager(\n",
        "    backend=backend, optimization_level=3\n",
        ")\n",
        "\n",
        "# Transpile the AQC-optimized circuit (compressed + subsequent step)\n",
        "isa_circuit = pass_manager.run(aqc_final_circuit)\n",
        "isa_observable = observable.apply_layout(isa_circuit.layout)\n",
        "print(\n",
        "    \"AQC circuit depth:\",\n",
        "    isa_circuit.depth(lambda x: x.operation.num_qubits == 2),\n",
        ")\n",
        "\n",
        "# Transpile the baseline Trotter circuit (no AQC optimization)\n",
        "isa_baseline_circuit = pass_manager.run(baseline_circuit)\n",
        "isa_baseline_observable = observable.apply_layout(isa_baseline_circuit.layout)\n",
        "print(\n",
        "    \"Baseline Trotter circuit depth:\",\n",
        "    isa_baseline_circuit.depth(lambda x: x.operation.num_qubits == 2),\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "60aec566",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute-using-qiskit-primitives\" />\n",
        "\n",
        "### ステップ3: `Qiskit primitives`を使用して実行する\n",
        "\n",
        "偽のバックエンドを備えたプリミティブ [`EstimatorV2`](/docs/api/qiskit-ibm-runtime/estimator-v2) を使用して、AQC最適化回路とベースラインのトロッター回路の両方を実行し、それぞれについてZZ観測量を測定する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "241e24f2",
      "metadata": {},
      "outputs": [],
      "source": [
        "estimator = Estimator(backend)\n",
        "\n",
        "# Run both circuits\n",
        "aqc_result = estimator.run([(isa_circuit, isa_observable)]).result()\n",
        "baseline_result = estimator.run(\n",
        "    [(isa_baseline_circuit, isa_baseline_observable)]\n",
        ").result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0b980055",
      "metadata": {},
      "source": [
        "<span id=\"step-4-post-process-and-return-result-in-desired-classical-format\" />\n",
        "\n",
        "### ステップ4：後処理を行い、結果を希望の古典形式で返す\n",
        "\n",
        "両方の実行結果から期待値を求め、それらを正確な結果と比較する。 ベースラインとなるTrotter回路は、同じ回路深度においてAQCを使用しない場合の挙動を示しており、一方、AQC回路はテンソルネットワーク最適化による改善効果を示しています。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "af07a1d9",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Exact:              -0.7009\n",
            "Baseline Trotter:   -0.5400, |Δ| = 0.1609  (depth 27, 4 steps)\n",
            "AQC (3+1):          -0.5728, |Δ| = 0.1281  (depth 15, compressed+subsequent)\n"
          ]
        }
      ],
      "source": [
        "aqc_expval = aqc_result[0].data.evs.tolist()\n",
        "baseline_expval = baseline_result[0].data.evs.tolist()\n",
        "\n",
        "print(f\"Exact:              {exact_expval:.4f}\")\n",
        "print(\n",
        "    f\"Baseline Trotter:   {baseline_expval:.4f}, |\\u0394| = {np.abs(exact_expval - baseline_expval):.4f}  (depth {isa_baseline_circuit.depth(lambda x: x.operation.num_qubits == 2)}, {baseline_num_trotter_steps} steps)\"\n",
        ")\n",
        "print(\n",
        "    f\"AQC (3+1):          {aqc_expval:.4f}, |\\u0394| = {np.abs(exact_expval - aqc_expval):.4f}  (depth {isa_circuit.depth(lambda x: x.operation.num_qubits == 2)}, compressed+subsequent)\"\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "77c39ba8",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/77c39ba8-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "plt.style.use(\"seaborn-v0_8\")\n",
        "\n",
        "labels = [\n",
        "    f\"Baseline Trotter\\n({baseline_num_trotter_steps} steps, depth {isa_baseline_circuit.depth(lambda x: x.operation.num_qubits == 2)})\",\n",
        "    f\"AQC (3+1)\\n(depth {isa_circuit.depth(lambda x: x.operation.num_qubits == 2)})\",\n",
        "]\n",
        "values = [baseline_expval, aqc_expval]\n",
        "colors = [\"tab:orange\", \"tab:blue\"]\n",
        "\n",
        "plt.figure(figsize=(8, 5))\n",
        "bars = plt.bar(labels, values, color=colors, width=0.5)\n",
        "plt.axhline(\n",
        "    y=exact_expval,\n",
        "    color=\"tab:green\",\n",
        "    linestyle=\"--\",\n",
        "    linewidth=2,\n",
        "    label=f\"Exact ({exact_expval:.4f})\",\n",
        ")\n",
        "plt.ylabel(\"Expected Value\")\n",
        "plt.title(\n",
        "    \"AQC-Tensor (3 compressed + 1 uncompressed) vs Baseline Trotter (10-site XXZ)\"\n",
        ")\n",
        "plt.legend()\n",
        "for bar in bars:\n",
        "    y_val = bar.get_height()\n",
        "    plt.text(\n",
        "        bar.get_x() + bar.get_width() / 2.0,\n",
        "        y_val,\n",
        "        f\"{y_val:.4f}\",\n",
        "        ha=\"center\",\n",
        "        va=\"bottom\" if y_val >= 0 else \"top\",\n",
        "    )\n",
        "plt.axhline(y=0, color=\"black\", linewidth=0.3)\n",
        "plt.tight_layout()\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "37062efa",
      "metadata": {},
      "source": [
        "<span id=\"large-scale-hardware-example\" />\n",
        "\n",
        "## 大規模なハードウェアの例\n",
        "\n",
        "ここでは、より現実的な問題規模でAQC-Tensorを実証するため、50サイトXXZモデルへとスケールアップします。 ワークフローは小規模な例と同じです。AQCを用いて3つのトロッターステップを圧縮し、その後に1つの非圧縮ステップを追加します。\n",
        "\n",
        "この規模のシステムでは、行列のべき乗演算は現実的ではない（ $2^{50}$ 次元）ため、全時間に対して進化させた高精度MPSから、参照期待値を直接計算する。\n",
        "\n",
        "<span id=\"steps-1–4-combined\" />\n",
        "\n",
        "### 手順1～4をまとめて\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "b6c0f26a",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Target circuit:  depth 385\n",
            "Ansatz circuit:  depth 7, with 816 parameters\n",
            "Subsequent circuit: depth 12\n",
            "Baseline circuit:   depth 49 (4 steps, time=0.2667)\n",
            "Target MPS maximum bond dimension: 5\n",
            "Reference expectation value (from MPS): -0.738669\n",
            "2026-05-18 13:02:11.219150 Intermediate result: Fidelity 0.99795732\n",
            "2026-05-18 13:02:11.232256 Intermediate result: Fidelity 0.99822481\n",
            "2026-05-18 13:02:11.245160 Intermediate result: Fidelity 0.99829520\n",
            "2026-05-18 13:02:11.257765 Intermediate result: Fidelity 0.99832379\n",
            "2026-05-18 13:02:11.270280 Intermediate result: Fidelity 0.99836416\n",
            "2026-05-18 13:02:11.284116 Intermediate result: Fidelity 0.99840073\n",
            "2026-05-18 13:02:11.296856 Intermediate result: Fidelity 0.99846863\n",
            "2026-05-18 13:02:11.309602 Intermediate result: Fidelity 0.99865244\n",
            "2026-05-18 13:02:11.322012 Intermediate result: Fidelity 0.99872665\n",
            "2026-05-18 13:02:11.334195 Intermediate result: Fidelity 0.99892335\n",
            "2026-05-18 13:02:11.346570 Intermediate result: Fidelity 0.99901045\n",
            "2026-05-18 13:02:11.359202 Intermediate result: Fidelity 0.99907181\n",
            "2026-05-18 13:02:11.371511 Intermediate result: Fidelity 0.99911125\n",
            "2026-05-18 13:02:11.383870 Intermediate result: Fidelity 0.99918585\n",
            "2026-05-18 13:02:11.396184 Intermediate result: Fidelity 0.99921504\n",
            "2026-05-18 13:02:11.408543 Intermediate result: Fidelity 0.99924936\n",
            "2026-05-18 13:02:11.422557 Intermediate result: Fidelity 0.99929226\n",
            "2026-05-18 13:02:11.436275 Intermediate result: Fidelity 0.99933099\n",
            "2026-05-18 13:02:11.449511 Intermediate result: Fidelity 0.99935792\n",
            "2026-05-18 13:02:11.462093 Intermediate result: Fidelity 0.99937925\n",
            "2026-05-18 13:02:11.475783 Intermediate result: Fidelity 0.99940690\n",
            "2026-05-18 13:02:11.490254 Intermediate result: Fidelity 0.99944409\n",
            "2026-05-18 13:02:11.503292 Intermediate result: Fidelity 0.99946840\n",
            "2026-05-18 13:02:11.516064 Intermediate result: Fidelity 0.99949378\n",
            "2026-05-18 13:02:11.532861 Intermediate result: Fidelity 0.99951380\n",
            "2026-05-18 13:02:11.546182 Intermediate result: Fidelity 0.99955313\n",
            "2026-05-18 13:02:11.559168 Intermediate result: Fidelity 0.99955707\n",
            "2026-05-18 13:02:11.571753 Intermediate result: Fidelity 0.99959306\n",
            "2026-05-18 13:02:11.584257 Intermediate result: Fidelity 0.99960486\n",
            "2026-05-18 13:02:11.597610 Intermediate result: Fidelity 0.99961714\n",
            "2026-05-18 13:02:11.610106 Intermediate result: Fidelity 0.99962953\n",
            "2026-05-18 13:02:11.622515 Intermediate result: Fidelity 0.99963525\n",
            "2026-05-18 13:02:11.635543 Intermediate result: Fidelity 0.99964658\n",
            "2026-05-18 13:02:11.649044 Intermediate result: Fidelity 0.99965027\n",
            "2026-05-18 13:02:11.664148 Intermediate result: Fidelity 0.99965802\n",
            "2026-05-18 13:02:11.678033 Intermediate result: Fidelity 0.99966731\n",
            "2026-05-18 13:02:11.692714 Intermediate result: Fidelity 0.99967780\n",
            "2026-05-18 13:02:11.706753 Intermediate result: Fidelity 0.99968567\n",
            "2026-05-18 13:02:11.720780 Intermediate result: Fidelity 0.99969139\n",
            "2026-05-18 13:02:11.733471 Intermediate result: Fidelity 0.99969628\n",
            "2026-05-18 13:02:11.745998 Intermediate result: Fidelity 0.99970331\n",
            "2026-05-18 13:02:11.758424 Intermediate result: Fidelity 0.99970796\n",
            "2026-05-18 13:02:11.771986 Intermediate result: Fidelity 0.99971165\n",
            "2026-05-18 13:02:11.785841 Intermediate result: Fidelity 0.99971892\n",
            "2026-05-18 13:02:11.799105 Intermediate result: Fidelity 0.99972226\n",
            "2026-05-18 13:02:11.811623 Intermediate result: Fidelity 0.99972441\n",
            "2026-05-18 13:02:11.824114 Intermediate result: Fidelity 0.99972679\n",
            "2026-05-18 13:02:11.837179 Intermediate result: Fidelity 0.99972965\n",
            "2026-05-18 13:02:12.345479 Intermediate result: Fidelity 0.99972965\n",
            "Done after 49 iterations.\n",
            "<IBMBackend('ibm_pittsburgh')>\n",
            "AQC circuit depth: 71\n",
            "Baseline Trotter circuit depth: 111\n",
            "Job ID: d85kc6o0bvlc73d5nhn0\n"
          ]
        }
      ],
      "source": [
        "# -------------------------Step 1-------------------------\n",
        "\n",
        "# Define the 50-site spin chain\n",
        "L = 50\n",
        "edge_list = [(i - 1, i) for i in range(1, L)]\n",
        "even_edges = edge_list[::2]\n",
        "odd_edges = edge_list[1::2]\n",
        "coupling_map = CouplingMap(edge_list)\n",
        "\n",
        "# Random XXZ Hamiltonian\n",
        "np.random.seed(0)\n",
        "Js = np.random.rand(L - 1) + 0.5 * np.ones(L - 1)\n",
        "hamiltonian = SparsePauliOp(Pauli(\"I\" * L))\n",
        "for i, edge in enumerate(even_edges + odd_edges):\n",
        "    hamiltonian += SparsePauliOp.from_sparse_list(\n",
        "        [\n",
        "            (\"XX\", (edge), Js[i] / 2),\n",
        "            (\"YY\", (edge), Js[i] / 2),\n",
        "            (\"ZZ\", (edge), Js[i]),\n",
        "        ],\n",
        "        num_qubits=L,\n",
        "    )\n",
        "\n",
        "observable = SparsePauliOp.from_sparse_list(\n",
        "    [(\"ZZ\", (L // 2 - 1, L // 2), 1.0)], num_qubits=L\n",
        ")\n",
        "\n",
        "# Initial Néel state\n",
        "initial_state_circuit = QuantumCircuit(L)\n",
        "for i in range(L):\n",
        "    if i % 2:\n",
        "        initial_state_circuit.x(i)\n",
        "\n",
        "# Time parameters\n",
        "aqc_evolution_time = 0.2\n",
        "subsequent_evolution_time = aqc_evolution_time / 3\n",
        "total_evolution_time = aqc_evolution_time + subsequent_evolution_time\n",
        "\n",
        "# AQC target circuit (high-accuracy, 32 Trotter steps for AQC portion)\n",
        "aqc_target_num_trotter_steps = 32\n",
        "\n",
        "aqc_target_circuit = initial_state_circuit.copy()\n",
        "aqc_target_circuit.compose(\n",
        "    generate_time_evolution_circuit(\n",
        "        hamiltonian,\n",
        "        synthesis=SuzukiTrotter(reps=aqc_target_num_trotter_steps),\n",
        "        time=aqc_evolution_time,\n",
        "    ),\n",
        "    inplace=True,\n",
        ")\n",
        "\n",
        "# Generate ansatz from 1-step Trotter circuit\n",
        "aqc_good_circuit = initial_state_circuit.copy()\n",
        "aqc_good_circuit.compose(\n",
        "    generate_time_evolution_circuit(\n",
        "        hamiltonian,\n",
        "        synthesis=SuzukiTrotter(reps=1),\n",
        "        time=aqc_evolution_time,\n",
        "    ),\n",
        "    inplace=True,\n",
        ")\n",
        "\n",
        "aqc_ansatz, aqc_initial_parameters = generate_ansatz_from_circuit(\n",
        "    aqc_good_circuit\n",
        ")\n",
        "\n",
        "# Subsequent circuit: 1 non-compressed Trotter step\n",
        "subsequent_circuit = generate_time_evolution_circuit(\n",
        "    hamiltonian,\n",
        "    synthesis=SuzukiTrotter(reps=1),\n",
        "    time=subsequent_evolution_time,\n",
        ")\n",
        "\n",
        "# Baseline Trotter circuit: 4 Trotter steps over total evolution time, no AQC\n",
        "baseline_num_trotter_steps = 4\n",
        "baseline_circuit = initial_state_circuit.copy()\n",
        "baseline_circuit.compose(\n",
        "    generate_time_evolution_circuit(\n",
        "        hamiltonian,\n",
        "        synthesis=SuzukiTrotter(reps=baseline_num_trotter_steps),\n",
        "        time=total_evolution_time,\n",
        "    ),\n",
        "    inplace=True,\n",
        ")\n",
        "print(\n",
        "    f\"Target circuit:  depth {aqc_target_circuit.depth(lambda x: x.operation.num_qubits == 2)}\"\n",
        ")\n",
        "print(\n",
        "    f\"Ansatz circuit:  depth {aqc_ansatz.depth(lambda x: x.operation.num_qubits == 2)}, with {len(aqc_initial_parameters)} parameters\"\n",
        ")\n",
        "print(\n",
        "    f\"Subsequent circuit: depth {subsequent_circuit.depth(lambda x: x.operation.num_qubits == 2)}\"\n",
        ")\n",
        "print(\n",
        "    f\"Baseline circuit:   depth {baseline_circuit.depth(lambda x: x.operation.num_qubits == 2)} ({baseline_num_trotter_steps} steps, time={total_evolution_time:.4f})\"\n",
        ")\n",
        "\n",
        "# Build target MPS and compute reference expectation value\n",
        "simulator_settings = QuimbSimulator(\n",
        "    quimb.tensor.CircuitMPS, autodiff_backend=\"jax\"\n",
        ")\n",
        "aqc_target_mps = tensornetwork_from_circuit(\n",
        "    aqc_target_circuit, simulator_settings\n",
        ")\n",
        "print(\"Target MPS maximum bond dimension:\", aqc_target_mps.psi.max_bond())\n",
        "\n",
        "# For the reference expectation value, we need the full evolution (AQC + subsequent)\n",
        "# Build a high-accuracy full circuit for MPS reference\n",
        "full_target_circuit = initial_state_circuit.copy()\n",
        "full_target_circuit.compose(\n",
        "    generate_time_evolution_circuit(\n",
        "        hamiltonian,\n",
        "        synthesis=SuzukiTrotter(reps=aqc_target_num_trotter_steps),\n",
        "        time=total_evolution_time,\n",
        "    ),\n",
        "    inplace=True,\n",
        ")\n",
        "full_target_mps = tensornetwork_from_circuit(\n",
        "    full_target_circuit, simulator_settings\n",
        ")\n",
        "exact_expval = full_target_mps.local_expectation(\n",
        "    quimb.pauli(\"Z\") & quimb.pauli(\"Z\"), (L // 2 - 1, L // 2)\n",
        ").real.item()\n",
        "print(f\"Reference expectation value (from MPS): {exact_expval:.6f}\")\n",
        "\n",
        "# Optimize ansatz parameters\n",
        "objective = MaximizeStateFidelity(\n",
        "    aqc_target_mps, aqc_ansatz, simulator_settings\n",
        ")\n",
        "\n",
        "\n",
        "def callback(intermediate_result: OptimizeResult):\n",
        "    fidelity = 1 - intermediate_result.fun\n",
        "    print(\n",
        "        f\"{datetime.datetime.now()} Intermediate result: Fidelity {fidelity:.8f}\"\n",
        "    )\n",
        "\n",
        "\n",
        "result = minimize(\n",
        "    objective,\n",
        "    aqc_initial_parameters,\n",
        "    method=\"L-BFGS-B\",\n",
        "    jac=True,\n",
        "    options={\"maxiter\": 500},\n",
        "    callback=callback,\n",
        ")\n",
        "if result.status not in (0, 1, 99):\n",
        "    raise RuntimeError(\n",
        "        f\"Optimization failed: {result.message} (status={result.status})\"\n",
        "    )\n",
        "print(f\"Done after {result.nit} iterations.\")\n",
        "\n",
        "# Assemble the final AQC circuit: optimized ansatz + subsequent Trotter step\n",
        "aqc_final_circuit = aqc_ansatz.assign_parameters(result.x)\n",
        "aqc_final_circuit.compose(subsequent_circuit, inplace=True)\n",
        "\n",
        "# -------------------------Step 2-------------------------\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(min_num_qubits=127)\n",
        "print(backend)\n",
        "\n",
        "pass_manager = generate_preset_pass_manager(\n",
        "    backend=backend, optimization_level=3\n",
        ")\n",
        "isa_circuit = pass_manager.run(aqc_final_circuit)\n",
        "isa_observable = observable.apply_layout(isa_circuit.layout)\n",
        "print(\n",
        "    \"AQC circuit depth:\",\n",
        "    isa_circuit.depth(lambda x: x.operation.num_qubits == 2),\n",
        ")\n",
        "\n",
        "# Also transpile the baseline Trotter circuit (4 Trotter steps, no AQC)\n",
        "isa_baseline_circuit = pass_manager.run(baseline_circuit)\n",
        "isa_baseline_observable = observable.apply_layout(isa_baseline_circuit.layout)\n",
        "print(\n",
        "    \"Baseline Trotter circuit depth:\",\n",
        "    isa_baseline_circuit.depth(lambda x: x.operation.num_qubits == 2),\n",
        ")\n",
        "\n",
        "# -------------------------Step 3-------------------------\n",
        "\n",
        "# Submit both circuits in a single job\n",
        "estimator = Estimator(backend)\n",
        "estimator.options.environment.job_tags = [\"TUT_AQCTE\"]\n",
        "\n",
        "job = estimator.run(\n",
        "    [\n",
        "        (isa_circuit, isa_observable),\n",
        "        (isa_baseline_circuit, isa_baseline_observable),\n",
        "    ]\n",
        ")\n",
        "print(\"Job ID:\", job.job_id())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "a4dc23fd-494e-46cb-a8f5-d1cd444b96f4",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Exact (MPS):        -0.7387\n",
            "Baseline Trotter:   -0.5955, |Δ| = 0.1432\n",
            "AQC (3+1):          -0.6734, |Δ| = 0.0653\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/a4dc23fd-494e-46cb-a8f5-d1cd444b96f4-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# -------------------------Step 4-------------------------\n",
        "\n",
        "hw_results = job.result()\n",
        "aqc_expval = hw_results[0].data.evs.tolist()\n",
        "baseline_expval = hw_results[1].data.evs.tolist()\n",
        "\n",
        "print(f\"Exact (MPS):        {exact_expval:.4f}\")\n",
        "print(\n",
        "    f\"Baseline Trotter:   {baseline_expval:.4f}, |\\u0394| = {np.abs(exact_expval - baseline_expval):.4f}\"\n",
        ")\n",
        "print(\n",
        "    f\"AQC (3+1):          {aqc_expval:.4f}, |\\u0394| = {np.abs(exact_expval - aqc_expval):.4f}\"\n",
        ")\n",
        "\n",
        "labels = [\n",
        "    f\"Baseline Trotter\\n({baseline_num_trotter_steps} steps, depth {isa_baseline_circuit.depth(lambda x: x.operation.num_qubits == 2)})\",\n",
        "    f\"AQC (3+1)\\n(depth {isa_circuit.depth(lambda x: x.operation.num_qubits == 2)})\",\n",
        "]\n",
        "values = [baseline_expval, aqc_expval]\n",
        "colors = [\"tab:orange\", \"tab:blue\"]\n",
        "\n",
        "plt.figure(figsize=(8, 5))\n",
        "bars = plt.bar(labels, values, color=colors, width=0.5)\n",
        "plt.axhline(\n",
        "    y=exact_expval,\n",
        "    color=\"tab:green\",\n",
        "    linestyle=\"--\",\n",
        "    linewidth=2,\n",
        "    label=f\"Exact ({exact_expval:.4f})\",\n",
        ")\n",
        "plt.ylabel(\"Expected Value\")\n",
        "plt.title(\n",
        "    \"AQC-Tensor (3 compressed + 1 uncompressed) vs Baseline Trotter (50-site XXZ)\"\n",
        ")\n",
        "plt.legend()\n",
        "for bar in bars:\n",
        "    y_val = bar.get_height()\n",
        "    plt.text(\n",
        "        bar.get_x() + bar.get_width() / 2.0,\n",
        "        y_val,\n",
        "        f\"{y_val:.4f}\",\n",
        "        ha=\"center\",\n",
        "        va=\"bottom\" if y_val >= 0 else \"top\",\n",
        "    )\n",
        "plt.axhline(y=0, color=\"black\", linewidth=0.3)\n",
        "plt.tight_layout()\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "278bc002",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## 次のステップ\n",
        "\n",
        "<Admonition type=\"tip\" title=\"推奨事項\">\n",
        "  この作品が興味深かった方は、以下の資料もぜひご覧ください：\n",
        "\n",
        "  * [AQC-Tensor アドオンのドキュメント](https://qiskit.github.io/qiskit-addon-aqc-tensor/) — これには、準備された状態ではなく、目標となるユニタリ演算子を近似するようにパラメータ化された回路を最適化する、 **関連**するユニタリAQC手法が含まれています\n",
        "  * [エラーの軽減および抑制手法](/docs/guides/error-mitigation-and-suppression-techniques)\n",
        "  * [エラー軽減手法を組み合わせる](/docs/tutorials/combine-error-mitigation-techniques)\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "description": "Learn how to use AQC-Tensor to compress Trotterized time-evolution circuits for efficient execution on quantum hardware.",
    "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"
    },
    "title": "Approximate quantum compilation for time evolution circuits",
    "hours": 1.5,
    "qpuSeconds": 15
  },
  "nbformat": 4,
  "nbformat_minor": 5
}