{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "b3e994de-6477-421d-8a9a-6b20d45260ae",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"ハミルトンシミュレーションのためのQiskit関数テンプレートを構築する\"\n",
        "description: \"並列トランスパイルプログラムを作成し、 IBM Quantum Platform にデプロイして再利用可能なリモートサービスとして使用する方法。\"\n",
        "---\n",
        "\n",
        "<span id=\"build-a-qiskit-function-template-for-hamiltonian-simulation\" />\n",
        "\n",
        "# ハミルトンシミュレーションのためのQiskit関数テンプレートを構築する\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "31aee42c-1834-4fae-a05f-f78d8e5db7c0",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b51e81bf-0bbf-4f64-af1e-87fcb443d997",
      "metadata": {},
      "source": [
        "このテンプレートは、ユーザー定義のスピンのハミルトニアンに対する初期状態の時間発展をシミュレートするワークフローをカプセル化し、 [AQC-Tensor](https://qiskit.github.io/qiskit-addon-aqc-tensor/) Qiskit アドオンを使用して、指定された期待値のセットを返します。\n",
        "\n",
        "このテンプレートはQiskitパターンとして構成されており、以下のようなステップを踏む：\n",
        "\n",
        "<span id=\"1-collecting-input-and-mapping-the-problem\" />\n",
        "\n",
        "#### 1. 入力の収集と問題の整理\n",
        "\n",
        "このセクションでは、シミュレーションするハミルトニアン、 `QuantumCircuit` 形式の初期状態、期待値を推定するための観測量セット、AQCアドオンのオプション指定を入力として受け取ります。 このステップでは、必要な入力データがすべて存在し、それらが正しいフォーマットであることを検証する。\n",
        "\n",
        "入力された引数は、ワークフローに関連する量子回路と演算子の構築に使用される。 ターゲット回路が作成され、AQCアドオンを使用してこの回路の行列積状態表現が求められる。 これに続いて、アンサッツ回路が生成され、テンソルネットワーク法を用いて最適化され、残りの時間発展を実行する最終的な回路が生成される。\n",
        "\n",
        "<span id=\"2-prepare-the-generated-circuits-for-execution\" />\n",
        "\n",
        "#### 2. 生成された回路を実行準備する\n",
        "\n",
        "AQCアドオンから生成された回路は、選択したバックエンドで実行されるようにトランスパイルされる。 インスタンス [`EstimatorV2`](../api/qiskit-ibm-runtime/estimator-v2) インスタンスは、回路の実行を管理するためのエラー緩和オプションのデフォルトセットとともに作成される。\n",
        "\n",
        "<span id=\"3-execution\" />\n",
        "\n",
        "#### 3. 実行\n",
        "\n",
        "最後に、ansatz回路はトランスパイルされ、QPU上で実行され、指定されたすべての期待値の推定値を収集し、ユーザーがアクセスできるようにシリアライズ可能な形式で返される。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e451f954-1d8f-4687-a7e9-e4b0dfa170f3",
      "metadata": {},
      "source": [
        "<span id=\"write-the-function-template\" />\n",
        "\n",
        "## 関数テンプレートを記述する\n",
        "\n",
        "まず、 [AQC-Tensor Qiskit アドオン](https://qiskit.github.io/qiskit-addon-aqc-tensor/)を使用して、問題の説明をハードウェア上で実行するための減深回路にマッピングする、ハミルトニアンシミュレーションの関数テンプレートを作成します。\n",
        "\n",
        "このページをダウンロードして、ノートブックエディタでローカルに開くと、一部のコードセルに「 [magic」コマンド](https://ipython.readthedocs.io/en/stable/interactive/magics.html#cellmagic-writefile)が含まれているのが `%%writefile`わかります。 このマジックコマンドはコードを に保存 `./source_files/template_hamiltonian_simulation.py`します。これは、 Qiskit Serverless を使用してアップロードし、リモートで実行できる関数テンプレートです。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "115c14aa-5028-46f9-ab19-b49d47519636",
      "metadata": {},
      "source": [
        "<span id=\"collect-and-validate-the-inputs\" />\n",
        "\n",
        "### 入力値を収集し検証する\n",
        "\n",
        "テンプレートのインプットを得ることから始める。 この例では、ハミルトニアンシミュレーションに関連するドメイン固有の入力（ハミルトニアンや観測値など）と、能力固有のオプション（AQC-Tensorを使用してトロッター回路の初期レイヤーをどれだけ圧縮するか、あるいは、この例の一部であるデフォルトを超えるエラー抑制と緩和を微調整するための高度なオプションなど）があります。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "5e1e974b-feaa-47ce-abd1-65d442e8176e",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Writing ./source_files/template_hamiltonian_simulation.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile ./source_files/template_hamiltonian_simulation.py\n",
        "\n",
        "from qiskit import QuantumCircuit\n",
        "from qiskit_serverless import get_arguments, save_result\n",
        "\n",
        "\n",
        "# Extract parameters from arguments\n",
        "#\n",
        "# Do this at the top of the program so it fails early if any required arguments\n",
        "# are missing or invalid.\n",
        "\n",
        "arguments = get_arguments()\n",
        "\n",
        "dry_run = arguments.get(\"dry_run\", False)\n",
        "backend_name = arguments[\"backend_name\"]\n",
        "\n",
        "aqc_evolution_time = arguments[\"aqc_evolution_time\"]\n",
        "aqc_ansatz_num_trotter_steps = arguments[\"aqc_ansatz_num_trotter_steps\"]\n",
        "aqc_target_num_trotter_steps = arguments[\"aqc_target_num_trotter_steps\"]\n",
        "\n",
        "remainder_evolution_time = arguments[\"remainder_evolution_time\"]\n",
        "remainder_num_trotter_steps = arguments[\"remainder_num_trotter_steps\"]\n",
        "\n",
        "# Stop if this fidelity is achieved\n",
        "aqc_stopping_fidelity = arguments.get(\"aqc_stopping_fidelity\", 1.0)\n",
        "# Stop after this number of iterations, even if stopping fidelity is not achieved\n",
        "aqc_max_iterations = arguments.get(\"aqc_max_iterations\", 500)\n",
        "\n",
        "hamiltonian = arguments[\"hamiltonian\"]\n",
        "observable = arguments[\"observable\"]\n",
        "initial_state = arguments.get(\"initial_state\",\n",
        "    QuantumCircuit(hamiltonian.num_qubits))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "3f2629d5-5183-432a-8802-115a3b2f6ff7",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Appending to ./source_files/template_hamiltonian_simulation.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile --append ./source_files/template_hamiltonian_simulation.py\n",
        "\n",
        "import numpy as np\n",
        "import json\n",
        "from mergedeep import merge\n",
        "\n",
        "\n",
        "# Configure `EstimatorOptions`, to control the parameters\n",
        "# of the hardware experiment\n",
        "#\n",
        "# Set default options\n",
        "estimator_default_options = {\n",
        "    \"resilience\": {\n",
        "        \"measure_mitigation\": True,\n",
        "        \"zne_mitigation\": True,\n",
        "        \"zne\": {\n",
        "            \"amplifier\": \"gate_folding\",\n",
        "            \"noise_factors\": [1, 2, 3],\n",
        "            \"extrapolated_noise_factors\": list(np.linspace(0, 3, 31)),\n",
        "            \"extrapolator\": [\"exponential\", \"linear\", \"fallback\"],\n",
        "        },\n",
        "        \"measure_noise_learning\": {\n",
        "            \"num_randomizations\": 512,\n",
        "            \"shots_per_randomization\": 512,\n",
        "        },\n",
        "    },\n",
        "    \"twirling\": {\n",
        "        \"enable_gates\": True,\n",
        "        \"enable_measure\": True,\n",
        "        \"num_randomizations\": 300,\n",
        "        \"shots_per_randomization\": 100,\n",
        "        \"strategy\": \"active\",\n",
        "    },\n",
        "}\n",
        "# Merge with user-provided options\n",
        "estimator_options = merge(\n",
        "    arguments.get(\"estimator_options\", {}), estimator_default_options\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ac4e21bf-ccec-459e-984b-dc6a13ea56c8",
      "metadata": {},
      "source": [
        "関数テンプレートが実行されているとき、printステートメントを使用してログに情報を返すと、ワークロードの進捗状況をよりよく評価することができます。 以下は `estimator_options` 、実際に使用したEstimatorオプションの記録を印刷する簡単な例です。 AQC-Tensorの反復コンポーネント中の目的関数の値や、ハードウェア上での実行を目的とした最終的な命令セットアーキテクチャ（ISA）回路の2量子ビット深度など、実行中の進捗状況を報告するために、プログラム全体を通して同様の例が他にもたくさんある。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "be933b77-fb13-4875-9734-4226067bc8d2",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Appending to ./source_files/template_hamiltonian_simulation.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile --append ./source_files/template_hamiltonian_simulation.py\n",
        "\n",
        "print(\"estimator_options =\", json.dumps(estimator_options, indent=4))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fb65718c-8837-4610-87b7-59e6dc7abb80",
      "metadata": {},
      "source": [
        "<span id=\"validate-the-inputs\" />\n",
        "\n",
        "#### 入力の検証\n",
        "\n",
        "テンプレートをさまざまな入力で再利用できるようにするための重要な点は、入力の検証である。 以下のコードは、AQC-Tensorの停止フィデリティが適切に指定されているかどうかを検証し、指定されていない場合は、エラーを修正する方法について有益なエラーメッセージを返す例である。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "0af1aee2-5771-4ae1-82dc-3ec08943de54",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Appending to ./source_files/template_hamiltonian_simulation.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile --append ./source_files/template_hamiltonian_simulation.py\n",
        "\n",
        "# Perform parameter validation\n",
        "\n",
        "if not 0.0 < aqc_stopping_fidelity <= 1.0:\n",
        "    raise ValueError(\n",
        "        f\"Invalid stopping fidelity: {aqc_stopping_fidelity}.  \"\n",
        "        f\"It must be a positive float no greater than 1.\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0e5495ee-82e2-43dc-bca7-f8e81f8b6302",
      "metadata": {},
      "source": [
        "<span id=\"prepare-the-function-outputs\" />\n",
        "\n",
        "#### 関数の出力を準備する\n",
        "\n",
        "まず、関数テンプレートの出力をすべて保持する辞書を用意する。 キーは、ワークフロー全体を通してこの辞書に追加され、プログラムの最後に返される。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "1677fa7c-3b4a-4a24-b1e4-e03d9b3c49da",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Appending to ./source_files/template_hamiltonian_simulation.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile --append ./source_files/template_hamiltonian_simulation.py\n",
        "\n",
        "output = {}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3acd5522-a880-4de7-9251-2d68efc261ad",
      "metadata": {},
      "source": [
        "<span id=\"map-the-problem-and-pre-process-the-circuit-with-aqc\" />\n",
        "\n",
        "### 問題をマッピングし、AQCを用いて回路を前処理する\n",
        "\n",
        "AQC-Tensorの最適化は、Qiskitパターンのステップ1で行われる。  まず、目標とする状態を構築する。  この例では、AQC部分と同じハミルトニアンを同じ期間進化させるターゲット回路から構成される。  次に、等価回路から、より少ないトロッターステップで、アナザッツが生成される。  AQCアルゴリズムの主要部分では、このansatzを繰り返し目標状態に近づけていく。  最後に、その結果を、所望の進化時間に到達するために必要な残りのトロッターステップと組み合わせる。\n",
        "\n",
        "以下のコードにロギングの例が追加されている。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "92b59882-2844-4312-a09b-3da02c63f60b",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Appending to ./source_files/template_hamiltonian_simulation.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile --append ./source_files/template_hamiltonian_simulation.py\n",
        "\n",
        "import os\n",
        "os.environ[\"NUMBA_CACHE_DIR\"] = \"/data\"\n",
        "\n",
        "import datetime\n",
        "import quimb.tensor\n",
        "from scipy.optimize import OptimizeResult, minimize\n",
        "from qiskit.synthesis import SuzukiTrotter\n",
        "from qiskit_addon_utils.problem_generators import generate_time_evolution_circuit\n",
        "from qiskit_addon_aqc_tensor.ansatz_generation import (\n",
        "    generate_ansatz_from_circuit,\n",
        "    AnsatzBlock,\n",
        ")\n",
        "from qiskit_addon_aqc_tensor.simulation import (\n",
        "    tensornetwork_from_circuit,\n",
        "    compute_overlap,\n",
        ")\n",
        "from qiskit_addon_aqc_tensor.simulation.quimb import QuimbSimulator\n",
        "from qiskit_addon_aqc_tensor.objective import OneMinusFidelity\n",
        "\n",
        "print(\"Hamiltonian:\", hamiltonian)\n",
        "print(\"Observable:\", observable)\n",
        "simulator_settings = QuimbSimulator(quimb.tensor.CircuitMPS, autodiff_backend=\"jax\")\n",
        "\n",
        "# Construct the AQC target circuit\n",
        "aqc_target_circuit = initial_state.copy()\n",
        "if aqc_evolution_time:\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",
        "# Construct matrix-product state representation of the AQC target state\n",
        "aqc_target_mps = tensornetwork_from_circuit(aqc_target_circuit, simulator_settings)\n",
        "print(\"Target MPS maximum bond dimension:\", aqc_target_mps.psi.max_bond())\n",
        "output[\"target_bond_dimension\"] = aqc_target_mps.psi.max_bond()\n",
        "\n",
        "# Generate an ansatz and initial parameters from a Trotter circuit with fewer steps\n",
        "aqc_good_circuit = initial_state.copy()\n",
        "if aqc_evolution_time:\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",
        "aqc_ansatz, aqc_initial_parameters = generate_ansatz_from_circuit(aqc_good_circuit)\n",
        "print(\"Number of AQC parameters:\", len(aqc_initial_parameters))\n",
        "output[\"num_aqc_parameters\"] = len(aqc_initial_parameters)\n",
        "\n",
        "# Calculate the fidelity of ansatz circuit vs. the target state, before optimization\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(\"Starting fidelity of AQC portion:\", starting_fidelity)\n",
        "output[\"aqc_starting_fidelity\"] = starting_fidelity\n",
        "\n",
        "# Optimize the ansatz parameters by using MPS calculations\n",
        "def callback(intermediate_result: OptimizeResult):\n",
        "    fidelity = 1 - intermediate_result.fun\n",
        "    print(f\"{datetime.datetime.now()} Intermediate result: Fidelity {fidelity:.8f}\")\n",
        "    if intermediate_result.fun < stopping_point:\n",
        "        raise StopIteration\n",
        "\n",
        "\n",
        "objective = OneMinusFidelity(aqc_target_mps, aqc_ansatz, simulator_settings)\n",
        "stopping_point = 1.0 - aqc_stopping_fidelity\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 (\n",
        "    0,\n",
        "    1,\n",
        "    99,\n",
        "):  # 0 => success; 1 => max iterations reached;\n",
        "    # 99 => early termination via StopIteration\n",
        "    raise RuntimeError(\n",
        "        f\"Optimization failed: {result.message} (status={result.status})\"\n",
        "    )\n",
        "print(f\"Done after {result.nit} iterations.\")\n",
        "output[\"num_iterations\"] = result.nit\n",
        "aqc_final_parameters = result.x\n",
        "output[\"aqc_final_parameters\"] = list(aqc_final_parameters)\n",
        "\n",
        "# Construct an optimized circuit for initial portion of time evolution\n",
        "aqc_final_circuit = aqc_ansatz.assign_parameters(aqc_final_parameters)\n",
        "\n",
        "# Calculate fidelity after optimization\n",
        "aqc_final_mps = tensornetwork_from_circuit(aqc_final_circuit, simulator_settings)\n",
        "aqc_fidelity = abs(compute_overlap(aqc_final_mps, aqc_target_mps)) ** 2\n",
        "print(\"Fidelity of AQC portion:\", aqc_fidelity)\n",
        "output[\"aqc_fidelity\"] = aqc_fidelity\n",
        "\n",
        "# Construct final circuit, with remainder of time evolution\n",
        "final_circuit = aqc_final_circuit.copy()\n",
        "if remainder_evolution_time:\n",
        "    remainder_circuit = generate_time_evolution_circuit(\n",
        "        hamiltonian,\n",
        "        synthesis=SuzukiTrotter(reps=remainder_num_trotter_steps),\n",
        "        time=remainder_evolution_time,\n",
        "    )\n",
        "    final_circuit.compose(remainder_circuit, inplace=True)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ae8e53a6-2106-4753-ad1a-ebc146cd44ab",
      "metadata": {},
      "source": [
        "<span id=\"optimize-the-final-circuit-for-execution\" />\n",
        "\n",
        "### 最終回路の実行を最適化する\n",
        "\n",
        "ワークフローのAQC部分の後、 `final_circuit` 、通常通り[ハードウェア用にトランスパイルさ](/docs/guides/transpile#instruction-set-architecture)れる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "1db2749f-1285-48c6-8ec3-bc9f422686e2",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Appending to ./source_files/template_hamiltonian_simulation.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile --append ./source_files/template_hamiltonian_simulation.py\n",
        "\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.backend(backend_name)\n",
        "\n",
        "# Transpile PUBs (circuits and observables) to match ISA\n",
        "pass_manager = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
        "isa_circuit = pass_manager.run(final_circuit)\n",
        "isa_observable = observable.apply_layout(isa_circuit.layout)\n",
        "\n",
        "isa_2qubit_depth = isa_circuit.depth(lambda x: x.operation.num_qubits == 2)\n",
        "print(\"ISA circuit two-qubit depth:\", isa_2qubit_depth)\n",
        "output[\"twoqubit_depth\"] = isa_2qubit_depth"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c41b9c0e-1f00-454c-acff-c194cc16e03e",
      "metadata": {},
      "source": [
        "<span id=\"exit-early-if-using-dry-run-mode\" />\n",
        "\n",
        "#### ドライランモードを使用する場合は早めに終了してください\n",
        "\n",
        "ドライ・ラン・モードが選択されている場合、プログラムはハードウェア上で実行される前に停止される。 これは、例えば、ハードウェア上で実行するかどうかを決定する前に、まずISA回路の2量子ビット深度を検査したい場合に便利である。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "e7c6c770-0453-4ad7-9a3e-20a47208768a",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Appending to ./source_files/template_hamiltonian_simulation.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile --append ./source_files/template_hamiltonian_simulation.py\n",
        "\n",
        "# Exit now if dry run; don't execute on hardware\n",
        "if dry_run:\n",
        "    import sys\n",
        "\n",
        "    print(\"Exiting before hardware execution since `dry_run` is True.\")\n",
        "    save_result(output)\n",
        "    sys.exit(0)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3a603817-abaf-4403-beea-cca838a59577",
      "metadata": {},
      "source": [
        "<span id=\"execute-the-circuit-on-hardware\" />\n",
        "\n",
        "#### 回路をハードウェア上で実行する\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "b7525014-a473-4d9d-b7cb-9c590f2364ae",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Appending to ./source_files/template_hamiltonian_simulation.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile --append ./source_files/template_hamiltonian_simulation.py\n",
        "\n",
        "# ## Step 3: Execute quantum experiments on backend\n",
        "from qiskit_ibm_runtime import EstimatorV2 as Estimator\n",
        "\n",
        "\n",
        "estimator = Estimator(backend, options=estimator_options)\n",
        "\n",
        "# Submit the underlying Estimator job. Note that this is not the\n",
        "# actual function job.\n",
        "job = estimator.run([(isa_circuit, isa_observable)])\n",
        "print(\"Job ID:\", job.job_id())\n",
        "output[\"job_id\"] = job.job_id()\n",
        "\n",
        "# Wait until job is complete\n",
        "hw_results = job.result()\n",
        "hw_results_dicts = [pub_result.data.__dict__ for pub_result in hw_results]\n",
        "\n",
        "# Save hardware results to serverless output dictionary\n",
        "output[\"hw_results\"] = hw_results_dicts\n",
        "\n",
        "# Reorganize expectation values\n",
        "hw_expvals = [pub_result_data[\"evs\"].tolist()\n",
        "    for pub_result_data in hw_results_dicts]\n",
        "\n",
        "# Save expectation values to Qiskit Serverless\n",
        "print(\"Hardware expectation values\", hw_expvals)\n",
        "output[\"hw_expvals\"] = hw_expvals[0]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "12df35c4-4f1c-48cb-a323-d0cf33422fab",
      "metadata": {},
      "source": [
        "<span id=\"save-the-output\" />\n",
        "\n",
        "#### 出力を保存する\n",
        "\n",
        "この関数テンプレートは、このハミルトニアン・シミュレーションのワークフローに関連するドメインレベルの出力（期待値）に加え、途中で生成された重要なメタデータを返します。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "bfb8ab87-c42d-4993-92bd-8b38364dc443",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Appending to ./source_files/template_hamiltonian_simulation.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile --append ./source_files/template_hamiltonian_simulation.py\n",
        "\n",
        "save_result(output)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "220f8bc8-4f04-41d3-86f1-15e9c2f45a56",
      "metadata": {},
      "source": [
        "<span id=\"deploy-the-function-to-ibm-quantum-platform\" />\n",
        "\n",
        "## 関数を IBM Quantum Platform にデプロイする\n",
        "\n",
        "前のセクションでは、リモートで実行するプログラムを作成した。 このセクションのコードは、そのプログラムをQiskit Serverlessにアップロードします。\n",
        "\n",
        "[IBM Quantum Platformの]()ダッシュボードにあるAPIキーで、 `qiskit-ibm-catalog` を使って `QiskitServerless` に認証し、プログラムをアップロードします。\n",
        "\n",
        "オプションで、 `save_account()` 認証情報を保存するために [IBM Cloud](/docs/guides/cloud-setup#cloud-save) を使用できます（アカウントの設定ガイドを参照）。 この操作は、認証情報を同じファイルに [`QiskitRuntimeService.save_account()`](/docs/api/qiskit-ibm-runtime/qiskit-runtime-service#save_account)書き込むことに注意してください。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "313bd03b-bf9b-4e6c-aa05-1fe8def3868d",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_catalog import QiskitServerless, QiskitFunction\n",
        "\n",
        "# Authenticate to the remote cluster and submit the pattern\n",
        "# for remote execution\n",
        "serverless = QiskitServerless()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e9c495d4-cdab-4329-b65d-d111029aee64",
      "metadata": {},
      "source": [
        "このプログラムにはカスタム `pip` の依存関係がある。  `QiskitFunction` インスタンスを構築する際に、それらを `dependencies` 配列に追加する：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "ca386323-d92d-4c41-908b-1670324e1264",
      "metadata": {},
      "outputs": [],
      "source": [
        "template = QiskitFunction(\n",
        "    title=\"template_hamiltonian_simulation\",\n",
        "    entrypoint=\"template_hamiltonian_simulation.py\",\n",
        "    working_dir=\"./source_files/\",\n",
        "    dependencies=[\n",
        "        \"qiskit-addon-utils~=0.1.0\",\n",
        "        \"qiskit-addon-aqc-tensor[quimb-jax]~=0.1.2\",\n",
        "        \"mergedeep==1.3.4\",\n",
        "    ],\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "80a2c6b5-1f1e-4e90-9b1f-75907caf1df3",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "QiskitFunction(template_hamiltonian_simulation)"
            ]
          },
          "execution_count": 14,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "serverless.upload(template)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "06677105-627a-4948-aac7-071f44327a0b",
      "metadata": {},
      "source": [
        "最後に、プログラムが正常にアップロードされたかどうかを確認するには、 `serverless.list()` を使用します：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "11f14088-8eca-4a99-a291-3f37a61b0d26",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              " QiskitFunction(template_hamiltonian_simulation),\n"
            ]
          },
          "execution_count": 15,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "serverless.list()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "385bda3e-73de-413c-8e45-cf7047303219",
      "metadata": {},
      "source": [
        "<span id=\"run-the-function-template-remotely\" />\n",
        "\n",
        "## 関数テンプレートをリモートで実行する\n",
        "\n",
        "関数テンプレートがアップロードされたので、Qiskit Serverlessでリモート実行できる。 まず、テンプレートを名前で読み込む：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "d4ff8dea-95ab-4cc9-92b9-e28e277e76f2",
      "metadata": {},
      "outputs": [],
      "source": [
        "template = serverless.load(\"template_hamiltonian_simulation\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "57964962-87e9-4c0b-a717-cb620019960e",
      "metadata": {},
      "source": [
        "次に、ハミルトニアンシミュレーションのために、ドメインレベルの入力でテンプレートを実行します。 この例では、ランダムな結合を持つ50量子ビットのXXZモデルと、初期状態と観測量を指定する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "e5d1555c-9abb-4fef-b8a2-f8d1b723df01",
      "metadata": {},
      "outputs": [],
      "source": [
        "from itertools import chain\n",
        "import numpy as np\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "\n",
        "L = 50\n",
        "\n",
        "# Generate the edge list for this spin-chain\n",
        "edges = [(i, i + 1) for i in range(L - 1)]\n",
        "# Generate an edge-coloring so we can make hw-efficient circuits\n",
        "edges = edges[::2] + edges[1::2]\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",
        "\n",
        "hamiltonian = SparsePauliOp.from_sparse_list(\n",
        "    chain.from_iterable(\n",
        "        [\n",
        "            [\n",
        "                (\"XX\", (i, j), Js[i] / 2),\n",
        "                (\"YY\", (i, j), Js[i] / 2),\n",
        "                (\"ZZ\", (i, j), Js[i]),\n",
        "            ]\n",
        "            for i, j in edges\n",
        "        ]\n",
        "    ),\n",
        "    num_qubits=L,\n",
        ")\n",
        "observable = SparsePauliOp.from_sparse_list(\n",
        "    [(\"ZZ\", (L // 2 - 1, L // 2), 1.0)], num_qubits=L\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "id": "7ec5ab02-280c-4c04-8e63-e5354eb8ebb9",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "\n",
        "initial_state = QuantumCircuit(L)\n",
        "for i in range(L):\n",
        "    if i % 2:\n",
        "        initial_state.x(i)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "id": "ac8d8fec-0290-4d6b-a18c-afd02acfa850",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "853b0edb-d63f-4629-be71-398b6dcf33cb\n"
          ]
        }
      ],
      "source": [
        "job = template.run(\n",
        "    dry_run=True,\n",
        "    initial_state=initial_state,\n",
        "    hamiltonian=hamiltonian,\n",
        "    observable=observable,\n",
        "    backend_name=\"ibm_fez\",\n",
        "    estimator_options={},\n",
        "    aqc_evolution_time=0.2,\n",
        "    aqc_ansatz_num_trotter_steps=1,\n",
        "    aqc_target_num_trotter_steps=32,\n",
        "    remainder_evolution_time=0.2,\n",
        "    remainder_num_trotter_steps=4,\n",
        "    aqc_max_iterations=300,\n",
        ")\n",
        "print(job.job_id)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2249cabc-6821-4d84-b4d8-e519c2d94a5c",
      "metadata": {},
      "source": [
        "ジョブのステータスを確認する：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "id": "ed3b744d-cb00-43e0-907c-34dfebe2fa9b",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'QUEUED'"
            ]
          },
          "execution_count": 20,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "job.status()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "83751f45-ab37-4037-bc77-d1aef91ed46c",
      "metadata": {},
      "source": [
        "ジョブの実行後、 `print()` 出力から作成されたログをフェッチできる。 これらは、ハミルトニアン・シミュレーションのワークフローの進捗状況について、実用的な情報を提供することができる。 例えば、AQCの反復コンポーネント中の目的関数の値や、ハードウェア上で実行することを意図した最終的なISA回路の2量子ビット深さなどである。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "id": "3be62464-18b0-4598-b386-0ac0cc9cccb6",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "No logs yet.\n"
          ]
        }
      ],
      "source": [
        "print(job.logs())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a8384509-2a9d-44e6-a729-40464ff52bea",
      "metadata": {},
      "source": [
        "結果が出るまで、残りのプログラムをブロックする。 仕事が終わったら、結果を取り出すことができる。 これらには、ハミルトニアン・シミュレーションのドメインレベルの出力（期待値）や有用なメタデータが含まれる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "id": "fc678bcd-539d-4970-86e0-9a69f0a367ef",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "{'target_bond_dimension': 5,\n",
              " 'num_aqc_parameters': 816,\n",
              " 'aqc_starting_fidelity': 0.9914382555614002,\n",
              " 'num_iterations': 72,\n",
              " 'aqc_fidelity': 0.9998108844412502,\n",
              " 'twoqubit_depth': 33}"
            ]
          },
          "execution_count": 22,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "result = job.result()\n",
        "\n",
        "del result[\n",
        "    \"aqc_final_parameters\"\n",
        "]  # the list is too long to conveniently display here\n",
        "result"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "12b0ccfe-325a-4939-81e7-58d94557990d",
      "metadata": {},
      "source": [
        "ジョブが完了すると、ログ出力全体が利用可能になる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "id": "cb722373-cbfb-45a7-a2b5-d7a97e18ee6c",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "2024-12-17 14:50:15,580\tINFO job_manager.py:531 -- Runtime env is setting up.\n",
            "estimator_options = {\n",
            "    \"resilience\": {\n",
            "        \"measure_mitigation\": true,\n",
            "        \"zne_mitigation\": true,\n",
            "        \"zne\": {\n",
            "            \"amplifier\": \"gate_folding\",\n",
            "            \"noise_factors\": [\n",
            "                1,\n",
            "                2,\n",
            "                3\n",
            "            ],\n",
            "            \"extrapolated_noise_factors\": [\n",
            "                0.0,\n",
            "                0.1,\n",
            "                0.2,\n",
            "                0.30000000000000004,\n",
            "                0.4,\n",
            "                0.5,\n",
            "                0.6000000000000001,\n",
            "                0.7000000000000001,\n",
            "                0.8,\n",
            "                0.9,\n",
            "                1.0,\n",
            "                1.1,\n",
            "                1.2000000000000002,\n",
            "                1.3,\n",
            "                1.4000000000000001,\n",
            "                1.5,\n",
            "                1.6,\n",
            "                1.7000000000000002,\n",
            "                1.8,\n",
            "                1.9000000000000001,\n",
            "                2.0,\n",
            "                2.1,\n",
            "                2.2,\n",
            "                2.3000000000000003,\n",
            "                2.4000000000000004,\n",
            "                2.5,\n",
            "                2.6,\n",
            "                2.7,\n",
            "                2.8000000000000003,\n",
            "                2.9000000000000004,\n",
            "                3.0\n",
            "            ],\n",
            "            \"extrapolator\": [\n",
            "                \"exponential\",\n",
            "                \"linear\",\n",
            "                \"fallback\"\n",
            "            ]\n",
            "        },\n",
            "        \"measure_noise_learning\": {\n",
            "            \"num_randomizations\": 512,\n",
            "            \"shots_per_randomization\": 512\n",
            "        }\n",
            "    },\n",
            "    \"twirling\": {\n",
            "        \"enable_gates\": true,\n",
            "        \"enable_measure\": true,\n",
            "        \"num_randomizations\": 300,\n",
            "        \"shots_per_randomization\": 100,\n",
            "        \"strategy\": \"active\"\n",
            "    }\n",
            "}\n",
            "Hamiltonian: SparsePauliOp(['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXX', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYY', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZ', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'XXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'YYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'ZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXI', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYI', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZI', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],\n",
            "              coeffs=[0.52440675+0.j, 0.52440675+0.j, 1.0488135 +0.j, 0.55138169+0.j,\n",
            " 0.55138169+0.j, 1.10276338+0.j, 0.4618274 +0.j, 0.4618274 +0.j,\n",
            " 0.9236548 +0.j, 0.46879361+0.j, 0.46879361+0.j, 0.93758721+0.j,\n",
            " 0.73183138+0.j, 0.73183138+0.j, 1.46366276+0.j, 0.64586252+0.j,\n",
            " 0.64586252+0.j, 1.29172504+0.j, 0.53402228+0.j, 0.53402228+0.j,\n",
            " 1.06804456+0.j, 0.28551803+0.j, 0.28551803+0.j, 0.57103606+0.j,\n",
            " 0.2601092 +0.j, 0.2601092 +0.j, 0.5202184 +0.j, 0.63907838+0.j,\n",
            " 0.63907838+0.j, 1.27815675+0.j, 0.73930917+0.j, 0.73930917+0.j,\n",
            " 1.47861834+0.j, 0.48073968+0.j, 0.48073968+0.j, 0.96147936+0.j,\n",
            " 0.30913721+0.j, 0.30913721+0.j, 0.61827443+0.j, 0.32167664+0.j,\n",
            " 0.32167664+0.j, 0.64335329+0.j, 0.51092416+0.j, 0.51092416+0.j,\n",
            " 1.02184832+0.j, 0.38227781+0.j, 0.38227781+0.j, 0.76455561+0.j,\n",
            " 0.47807517+0.j, 0.47807517+0.j, 0.95615033+0.j, 0.2593949 +0.j,\n",
            " 0.2593949 +0.j, 0.5187898 +0.j, 0.55604786+0.j, 0.55604786+0.j,\n",
            " 1.11209572+0.j, 0.72187404+0.j, 0.72187404+0.j, 1.44374808+0.j,\n",
            " 0.42975395+0.j, 0.42975395+0.j, 0.8595079 +0.j, 0.5988156 +0.j,\n",
            " 0.5988156 +0.j, 1.1976312 +0.j, 0.58338336+0.j, 0.58338336+0.j,\n",
            " 1.16676672+0.j, 0.35519128+0.j, 0.35519128+0.j, 0.71038256+0.j,\n",
            " 0.40771418+0.j, 0.40771418+0.j, 0.81542835+0.j, 0.60759468+0.j,\n",
            " 0.60759468+0.j, 1.21518937+0.j, 0.52244159+0.j, 0.52244159+0.j,\n",
            " 1.04488318+0.j, 0.57294706+0.j, 0.57294706+0.j, 1.14589411+0.j,\n",
            " 0.6958865 +0.j, 0.6958865 +0.j, 1.391773  +0.j, 0.44172076+0.j,\n",
            " 0.44172076+0.j, 0.88344152+0.j, 0.51444746+0.j, 0.51444746+0.j,\n",
            " 1.02889492+0.j, 0.71279832+0.j, 0.71279832+0.j, 1.42559664+0.j,\n",
            " 0.29356465+0.j, 0.29356465+0.j, 0.5871293 +0.j, 0.66630992+0.j,\n",
            " 0.66630992+0.j, 1.33261985+0.j, 0.68500607+0.j, 0.68500607+0.j,\n",
            " 1.37001215+0.j, 0.64957928+0.j, 0.64957928+0.j, 1.29915856+0.j,\n",
            " 0.64026459+0.j, 0.64026459+0.j, 1.28052918+0.j, 0.56996051+0.j,\n",
            " 0.56996051+0.j, 1.13992102+0.j, 0.72233446+0.j, 0.72233446+0.j,\n",
            " 1.44466892+0.j, 0.45733097+0.j, 0.45733097+0.j, 0.91466194+0.j,\n",
            " 0.63711684+0.j, 0.63711684+0.j, 1.27423369+0.j, 0.53421697+0.j,\n",
            " 0.53421697+0.j, 1.06843395+0.j, 0.55881775+0.j, 0.55881775+0.j,\n",
            " 1.1176355 +0.j, 0.558467  +0.j, 0.558467  +0.j, 1.116934  +0.j,\n",
            " 0.59091015+0.j, 0.59091015+0.j, 1.1818203 +0.j, 0.46851598+0.j,\n",
            " 0.46851598+0.j, 0.93703195+0.j, 0.28011274+0.j, 0.28011274+0.j,\n",
            " 0.56022547+0.j, 0.58531893+0.j, 0.58531893+0.j, 1.17063787+0.j,\n",
            " 0.31446315+0.j, 0.31446315+0.j, 0.6289263 +0.j])\n",
            "Observable: SparsePauliOp(['IIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIII'],\n",
            "              coeffs=[1.+0.j])\n",
            "Target MPS maximum bond dimension: 5\n",
            "Number of AQC parameters: 816\n",
            "Starting fidelity of AQC portion: 0.9914382555614002\n",
            "2024-12-17 14:52:23.400028 Intermediate result: Fidelity 0.99764093\n",
            "2024-12-17 14:52:23.429669 Intermediate result: Fidelity 0.99788003\n",
            "2024-12-17 14:52:23.459674 Intermediate result: Fidelity 0.99795970\n",
            "2024-12-17 14:52:23.489666 Intermediate result: Fidelity 0.99799067\n",
            "2024-12-17 14:52:23.518545 Intermediate result: Fidelity 0.99803401\n",
            "2024-12-17 14:52:23.546952 Intermediate result: Fidelity 0.99809821\n",
            "2024-12-17 14:52:23.575271 Intermediate result: Fidelity 0.99824660\n",
            "2024-12-17 14:52:23.604049 Intermediate result: Fidelity 0.99845326\n",
            "2024-12-17 14:52:23.632709 Intermediate result: Fidelity 0.99870497\n",
            "2024-12-17 14:52:23.660527 Intermediate result: Fidelity 0.99891442\n",
            "2024-12-17 14:52:23.688273 Intermediate result: Fidelity 0.99904488\n",
            "2024-12-17 14:52:23.716105 Intermediate result: Fidelity 0.99914438\n",
            "2024-12-17 14:52:23.744336 Intermediate result: Fidelity 0.99922827\n",
            "2024-12-17 14:52:23.773399 Intermediate result: Fidelity 0.99929071\n",
            "2024-12-17 14:52:23.801482 Intermediate result: Fidelity 0.99932432\n",
            "2024-12-17 14:52:23.830466 Intermediate result: Fidelity 0.99936460\n",
            "2024-12-17 14:52:23.860738 Intermediate result: Fidelity 0.99938891\n",
            "2024-12-17 14:52:23.889958 Intermediate result: Fidelity 0.99940607\n",
            "2024-12-17 14:52:23.918703 Intermediate result: Fidelity 0.99941965\n",
            "2024-12-17 14:52:23.949744 Intermediate result: Fidelity 0.99944337\n",
            "2024-12-17 14:52:23.980871 Intermediate result: Fidelity 0.99946875\n",
            "2024-12-17 14:52:24.012124 Intermediate result: Fidelity 0.99949009\n",
            "2024-12-17 14:52:24.044359 Intermediate result: Fidelity 0.99952191\n",
            "2024-12-17 14:52:24.075840 Intermediate result: Fidelity 0.99953669\n",
            "2024-12-17 14:52:24.106303 Intermediate result: Fidelity 0.99955242\n",
            "2024-12-17 14:52:24.139329 Intermediate result: Fidelity 0.99958412\n",
            "2024-12-17 14:52:24.169725 Intermediate result: Fidelity 0.99960176\n",
            "2024-12-17 14:52:24.198749 Intermediate result: Fidelity 0.99961606\n",
            "2024-12-17 14:52:24.227874 Intermediate result: Fidelity 0.99963811\n",
            "2024-12-17 14:52:24.256818 Intermediate result: Fidelity 0.99964383\n",
            "2024-12-17 14:52:24.285889 Intermediate result: Fidelity 0.99964717\n",
            "2024-12-17 14:52:24.315228 Intermediate result: Fidelity 0.99966064\n",
            "2024-12-17 14:52:24.345322 Intermediate result: Fidelity 0.99966517\n",
            "2024-12-17 14:52:24.374921 Intermediate result: Fidelity 0.99967089\n",
            "2024-12-17 14:52:24.404309 Intermediate result: Fidelity 0.99968305\n",
            "2024-12-17 14:52:24.432664 Intermediate result: Fidelity 0.99968889\n",
            "2024-12-17 14:52:24.461639 Intermediate result: Fidelity 0.99969997\n",
            "2024-12-17 14:52:24.491244 Intermediate result: Fidelity 0.99971666\n",
            "2024-12-17 14:52:24.520354 Intermediate result: Fidelity 0.99972441\n",
            "2024-12-17 14:52:24.549965 Intermediate result: Fidelity 0.99973561\n",
            "2024-12-17 14:52:24.583464 Intermediate result: Fidelity 0.99973811\n",
            "2024-12-17 14:52:24.617537 Intermediate result: Fidelity 0.99974074\n",
            "2024-12-17 14:52:24.652247 Intermediate result: Fidelity 0.99974467\n",
            "2024-12-17 14:52:24.686831 Intermediate result: Fidelity 0.99974991\n",
            "2024-12-17 14:52:24.725476 Intermediate result: Fidelity 0.99975230\n",
            "2024-12-17 14:52:24.764637 Intermediate result: Fidelity 0.99975373\n",
            "2024-12-17 14:52:24.802499 Intermediate result: Fidelity 0.99975552\n",
            "2024-12-17 14:52:24.839960 Intermediate result: Fidelity 0.99975885\n",
            "2024-12-17 14:52:24.877472 Intermediate result: Fidelity 0.99976469\n",
            "2024-12-17 14:52:24.916233 Intermediate result: Fidelity 0.99976517\n",
            "2024-12-17 14:52:24.993750 Intermediate result: Fidelity 0.99976875\n",
            "2024-12-17 14:52:25.034953 Intermediate result: Fidelity 0.99976887\n",
            "2024-12-17 14:52:25.076197 Intermediate result: Fidelity 0.99977244\n",
            "2024-12-17 14:52:25.112340 Intermediate result: Fidelity 0.99977638\n",
            "2024-12-17 14:52:25.149947 Intermediate result: Fidelity 0.99977828\n",
            "2024-12-17 14:52:25.190049 Intermediate result: Fidelity 0.99978174\n",
            "2024-12-17 14:52:25.310903 Intermediate result: Fidelity 0.99978222\n",
            "2024-12-17 14:52:25.347512 Intermediate result: Fidelity 0.99978508\n",
            "2024-12-17 14:52:25.385201 Intermediate result: Fidelity 0.99978543\n",
            "2024-12-17 14:52:25.457436 Intermediate result: Fidelity 0.99978770\n",
            "2024-12-17 14:52:25.497133 Intermediate result: Fidelity 0.99978818\n",
            "2024-12-17 14:52:25.541179 Intermediate result: Fidelity 0.99978913\n",
            "2024-12-17 14:52:25.584791 Intermediate result: Fidelity 0.99978937\n",
            "2024-12-17 14:52:25.621484 Intermediate result: Fidelity 0.99979068\n",
            "2024-12-17 14:52:25.655847 Intermediate result: Fidelity 0.99979211\n",
            "2024-12-17 14:52:25.691710 Intermediate result: Fidelity 0.99979700\n",
            "2024-12-17 14:52:25.767711 Intermediate result: Fidelity 0.99979759\n",
            "2024-12-17 14:52:25.804517 Intermediate result: Fidelity 0.99979807\n",
            "2024-12-17 14:52:25.839394 Intermediate result: Fidelity 0.99980236\n",
            "2024-12-17 14:52:25.874438 Intermediate result: Fidelity 0.99980296\n",
            "2024-12-17 14:52:25.909900 Intermediate result: Fidelity 0.99980320\n",
            "2024-12-17 14:52:26.713044 Intermediate result: Fidelity 0.99980320\n",
            "Done after 72 iterations.\n",
            "Fidelity of AQC portion: 0.9998108844412502\n",
            "ISA circuit two-qubit depth: 33\n",
            "Exiting before hardware execution since `dry_run` is True.\n",
            "\n"
          ]
        }
      ],
      "source": [
        "print(job.logs())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "196d6261-e26b-4057-ae55-19f003fdc10a",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## 次のステップ\n",
        "\n",
        "<Admonition type=\"info\" title=\"推奨事項\">\n",
        "  AQC-TensorのQiskitアドオンを深く掘り下げるには、 [Improved Trotterized Time Evolution with Approximate Quantum Compilation](/docs/tutorials/approximate-quantum-compilation-for-time-evolution) チュートリアルか [qiskit-addon-aqc-tensor](https://github.com/Qiskit/qiskit-addon-aqc-tensor) リポジトリをご覧ください。\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "20502fe4-7940-40fa-a978-64cc3ff6c1b1",
      "metadata": {
        "tags": [
          "id-full-source"
        ]
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Overwriting ./source_files/template_hamiltonian_simulation_full.py\n"
          ]
        }
      ],
      "source": [
        "%%writefile ./source_files/template_hamiltonian_simulation_full.py\n",
        "\n",
        "from qiskit import QuantumCircuit\n",
        "from qiskit_serverless import get_arguments, save_result\n",
        "\n",
        "\n",
        "# Extract parameters from arguments\n",
        "#\n",
        "# Do this at the top of the program so it fails early\n",
        "# if any required arguments are missing or invalid.\n",
        "\n",
        "arguments = get_arguments()\n",
        "\n",
        "dry_run = arguments.get(\"dry_run\", False)\n",
        "backend_name = arguments[\"backend_name\"]\n",
        "\n",
        "aqc_evolution_time = arguments[\"aqc_evolution_time\"]\n",
        "aqc_ansatz_num_trotter_steps = arguments[\"aqc_ansatz_num_trotter_steps\"]\n",
        "aqc_target_num_trotter_steps = arguments[\"aqc_target_num_trotter_steps\"]\n",
        "\n",
        "remainder_evolution_time = arguments[\"remainder_evolution_time\"]\n",
        "remainder_num_trotter_steps = arguments[\"remainder_num_trotter_steps\"]\n",
        "\n",
        "# Stop if this fidelity is achieved\n",
        "aqc_stopping_fidelity = arguments.get(\"aqc_stopping_fidelity\", 1.0)\n",
        "# Stop after this number of iterations, even if stopping fidelity is not achieved\n",
        "aqc_max_iterations = arguments.get(\"aqc_max_iterations\", 500)\n",
        "\n",
        "hamiltonian = arguments[\"hamiltonian\"]\n",
        "observable = arguments[\"observable\"]\n",
        "initial_state = arguments.get(\"initial_state\", QuantumCircuit(hamiltonian.num_qubits))\n",
        "\n",
        "import numpy as np\n",
        "import json\n",
        "from mergedeep import merge\n",
        "\n",
        "\n",
        "# Configure `EstimatorOptions` to control the hardware experiment's parameters\n",
        "#\n",
        "# Set default options\n",
        "estimator_default_options = {\n",
        "    \"resilience\": {\n",
        "        \"measure_mitigation\": True,\n",
        "        \"zne_mitigation\": True,\n",
        "        \"zne\": {\n",
        "            \"amplifier\": \"gate_folding\",\n",
        "            \"noise_factors\": [1, 2, 3],\n",
        "            \"extrapolated_noise_factors\": list(np.linspace(0, 3, 31)),\n",
        "            \"extrapolator\": [\"exponential\", \"linear\", \"fallback\"],\n",
        "        },\n",
        "        \"measure_noise_learning\": {\n",
        "            \"num_randomizations\": 512,\n",
        "            \"shots_per_randomization\": 512,\n",
        "        },\n",
        "    },\n",
        "    \"twirling\": {\n",
        "        \"enable_gates\": True,\n",
        "        \"enable_measure\": True,\n",
        "        \"num_randomizations\": 300,\n",
        "        \"shots_per_randomization\": 100,\n",
        "        \"strategy\": \"active\",\n",
        "    },\n",
        "}\n",
        "# Merge with user-provided options\n",
        "estimator_options = merge(\n",
        "    arguments.get(\"estimator_options\", {}), estimator_default_options\n",
        ")\n",
        "\n",
        "print(\"estimator_options =\", json.dumps(estimator_options, indent=4))\n",
        "\n",
        "# Perform parameter validation\n",
        "\n",
        "if not 0.0 < aqc_stopping_fidelity <= 1.0:\n",
        "    raise ValueError(\n",
        "        f\"Invalid stopping fidelity: {aqc_stopping_fidelity}.  \"\n",
        "        It must be a positive float no greater than 1.\"\n",
        "    )\n",
        "\n",
        "output = {}\n",
        "\n",
        "import os\n",
        "os.environ[\"NUMBA_CACHE_DIR\"] = \"/data\"\n",
        "\n",
        "import datetime\n",
        "import quimb.tensor\n",
        "from scipy.optimize import OptimizeResult, minimize\n",
        "from qiskit.synthesis import SuzukiTrotter\n",
        "from qiskit_addon_utils.problem_generators import generate_time_evolution_circuit\n",
        "from qiskit_addon_aqc_tensor.ansatz_generation import (\n",
        "    generate_ansatz_from_circuit,\n",
        "    AnsatzBlock,\n",
        ")\n",
        "from qiskit_addon_aqc_tensor.simulation import (\n",
        "    tensornetwork_from_circuit,\n",
        "    compute_overlap,\n",
        ")\n",
        "from qiskit_addon_aqc_tensor.simulation.quimb import QuimbSimulator\n",
        "from qiskit_addon_aqc_tensor.objective import OneMinusFidelity\n",
        "\n",
        "print(\"Hamiltonian:\", hamiltonian)\n",
        "print(\"Observable:\", observable)\n",
        "simulator_settings = QuimbSimulator(quimb.tensor.CircuitMPS, autodiff_backend=\"jax\")\n",
        "\n",
        "# Construct the AQC target circuit\n",
        "aqc_target_circuit = initial_state.copy()\n",
        "if aqc_evolution_time:\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",
        "# Construct matrix-product state representation of the AQC target state\n",
        "aqc_target_mps = tensornetwork_from_circuit(aqc_target_circuit, simulator_settings)\n",
        "print(\"Target MPS maximum bond dimension:\", aqc_target_mps.psi.max_bond())\n",
        "output[\"target_bond_dimension\"] = aqc_target_mps.psi.max_bond()\n",
        "\n",
        "# Generate an ansatz and initial parameters from a Trotter circuit with fewer steps\n",
        "aqc_good_circuit = initial_state.copy()\n",
        "if aqc_evolution_time:\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",
        "aqc_ansatz, aqc_initial_parameters = generate_ansatz_from_circuit(aqc_good_circuit)\n",
        "print(\"Number of AQC parameters:\", len(aqc_initial_parameters))\n",
        "output[\"num_aqc_parameters\"] = len(aqc_initial_parameters)\n",
        "\n",
        "# Calculate the fidelity of ansatz circuit vs. the target state, before optimization\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(\"Starting fidelity of AQC portion:\", starting_fidelity)\n",
        "output[\"aqc_starting_fidelity\"] = starting_fidelity\n",
        "\n",
        "# Optimize the ansatz parameters by using MPS calculations\n",
        "def callback(intermediate_result: OptimizeResult):\n",
        "    fidelity = 1 - intermediate_result.fun\n",
        "    print(f\"{datetime.datetime.now()} Intermediate result: Fidelity {fidelity:.8f}\")\n",
        "    if intermediate_result.fun < stopping_point:\n",
        "        raise StopIteration\n",
        "\n",
        "\n",
        "objective = OneMinusFidelity(aqc_target_mps, aqc_ansatz, simulator_settings)\n",
        "stopping_point = 1.0 - aqc_stopping_fidelity\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 (\n",
        "    0,\n",
        "    1,\n",
        "    99,\n",
        "):  # 0 => success; 1 => max iterations reached; 99 => early termination via StopIteration\n",
        "    raise RuntimeError(\n",
        "        f\"Optimization failed: {result.message} (status={result.status})\"\n",
        "    )\n",
        "print(f\"Done after {result.nit} iterations.\")\n",
        "output[\"num_iterations\"] = result.nit\n",
        "aqc_final_parameters = result.x\n",
        "output[\"aqc_final_parameters\"] = list(aqc_final_parameters)\n",
        "\n",
        "# Construct an optimized circuit for initial portion of time evolution\n",
        "aqc_final_circuit = aqc_ansatz.assign_parameters(aqc_final_parameters)\n",
        "\n",
        "# Calculate fidelity after optimization\n",
        "aqc_final_mps = tensornetwork_from_circuit(aqc_final_circuit, simulator_settings)\n",
        "aqc_fidelity = abs(compute_overlap(aqc_final_mps, aqc_target_mps)) ** 2\n",
        "print(\"Fidelity of AQC portion:\", aqc_fidelity)\n",
        "output[\"aqc_fidelity\"] = aqc_fidelity\n",
        "\n",
        "# Construct final circuit, with remainder of time evolution\n",
        "final_circuit = aqc_final_circuit.copy()\n",
        "if remainder_evolution_time:\n",
        "    remainder_circuit = generate_time_evolution_circuit(\n",
        "        hamiltonian,\n",
        "        synthesis=SuzukiTrotter(reps=remainder_num_trotter_steps),\n",
        "        time=remainder_evolution_time,\n",
        "    )\n",
        "    final_circuit.compose(remainder_circuit, inplace=True)\n",
        "\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.backend(backend_name)\n",
        "\n",
        "# Transpile PUBs (circuits and observables) to match ISA\n",
        "pass_manager = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
        "isa_circuit = pass_manager.run(final_circuit)\n",
        "isa_observable = observable.apply_layout(isa_circuit.layout)\n",
        "\n",
        "isa_2qubit_depth = isa_circuit.depth(lambda x: x.operation.num_qubits == 2)\n",
        "print(\"ISA circuit two-qubit depth:\", isa_2qubit_depth)\n",
        "output[\"twoqubit_depth\"] = isa_2qubit_depth\n",
        "\n",
        "# Exit now if dry run; don't execute on hardware\n",
        "if dry_run:\n",
        "    import sys\n",
        "\n",
        "    print(\"Exiting before hardware execution since `dry_run` is True.\")\n",
        "    save_result(output)\n",
        "    sys.exit(0)\n",
        "\n",
        "# ## Step 3: Execute quantum experiments on backend\n",
        "from qiskit_ibm_runtime import EstimatorV2 as Estimator\n",
        "\n",
        "\n",
        "estimator = Estimator(backend, options=estimator_options)\n",
        "\n",
        "# Submit the underlying Estimator job. Note that this is not the\n",
        "# actual function job.\n",
        "job = estimator.run([(isa_circuit, isa_observable)])\n",
        "print(\"Job ID:\", job.job_id())\n",
        "output[\"job_id\"] = job.job_id()\n",
        "\n",
        "# Wait until job is complete\n",
        "hw_results = job.result()\n",
        "hw_results_dicts = [pub_result.data.__dict__ for pub_result in hw_results]\n",
        "\n",
        "# Save hardware results to serverless output dictionary\n",
        "output[\"hw_results\"] = hw_results_dicts\n",
        "\n",
        "# Reorganize expectation values\n",
        "hw_expvals = [pub_result_data[\"evs\"].tolist()\n",
        "    for pub_result_data in hw_results_dicts]\n",
        "\n",
        "# Save expectation values to Qiskit Serverless\n",
        "output[\"hw_expvals\"] = hw_expvals[0]\n",
        "\n",
        "save_result(output)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d7f1776a-a8f6-43a3-85b7-33975c4eeec0",
      "metadata": {},
      "source": [
        "<Accordion>\n",
        "  <AccordionItem title=\"**完全なプログラムソースコード**\">\n",
        "    以下は、 `./source_files/template_hamiltonian_simulation.py` のソース全体を1つのコードブロックにしたものである。\n",
        "\n",
        "    <CodeCellPlaceholder tag=\"id-full-source\" />\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}