{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "b3e994de-6477-421d-8a9a-6b20d45260ae",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Créer un modèle de fonction Qiskit pour la simulation hamiltonienne\"\n",
        "description: \"Comment créer un programme de transpilation parallèle et le déployer sur IBM Quantum Platform afin de l'utiliser comme service distant réutilisable.\"\n",
        "---\n",
        "\n",
        "<span id=\"build-a-qiskit-function-template-for-hamiltonian-simulation\" />\n",
        "\n",
        "# Créer un modèle de fonction Qiskit pour la simulation hamiltonienne\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": [
        "Ce modèle encapsule un workflow permettant de simuler l'évolution temporelle d'un état initial par rapport à un hamiltonien basé sur le spin défini par l'utilisateur et renvoie un ensemble de valeurs attendues spécifiées à l'aide du module complémentaire [AQC-Tensor](https://qiskit.github.io/qiskit-addon-aqc-tensor/) Qiskit.\n",
        "\n",
        "Ce modèle est structuré comme un modèle Qiskit avec les étapes suivantes :\n",
        "\n",
        "<span id=\"1-collecting-input-and-mapping-the-problem\" />\n",
        "\n",
        "#### 1. Recueillir les informations et cartographier le problème\n",
        "\n",
        "Cette section prend en entrée le hamiltonien à simuler, un état initial sous la forme d'un `QuantumCircuit`, un ensemble d'observables pour estimer les valeurs d'espérance, et une spécification d'options pour le module complémentaire AQC. Cette étape permet de valider que toutes les données d'entrée requises sont présentes et qu'elles sont dans le bon format.\n",
        "\n",
        "Les arguments d'entrée sont ensuite utilisés pour construire les circuits quantiques et les opérateurs pertinents pour le flux de travail. Un circuit cible est créé et une représentation matricielle de l'état du produit de ce circuit est trouvée à l'aide du module complémentaire AQC. Ensuite, un circuit d'ansatz est généré et optimisé à l'aide de méthodes de réseau tensoriel, produisant un circuit final qui exécute le reste de l'évolution temporelle.\n",
        "\n",
        "<span id=\"2-prepare-the-generated-circuits-for-execution\" />\n",
        "\n",
        "#### 2. Préparer les circuits générés pour l'exécution\n",
        "\n",
        "Les circuits générés par l'addon AQC sont ensuite transposés pour être exécutés sur un backend choisi. Une instance [`EstimatorV2`](../api/qiskit-ibm-runtime/estimator-v2) est créée avec un ensemble d'options d'atténuation des erreurs par défaut pour gérer l'exécution du circuit.\n",
        "\n",
        "<span id=\"3-execution\" />\n",
        "\n",
        "#### 3. Exécution\n",
        "\n",
        "Enfin, le circuit d'ansatz est transpilé et exécuté sur une QPU et recueille des estimations pour toutes les valeurs d'espérance spécifiées, qui sont renvoyées dans un format sérialisable pour permettre à l'utilisateur d'y accéder.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e451f954-1d8f-4687-a7e9-e4b0dfa170f3",
      "metadata": {},
      "source": [
        "<span id=\"write-the-function-template\" />\n",
        "\n",
        "## Écrire le modèle de fonction\n",
        "\n",
        "Commencez par écrire un modèle de fonction pour la simulation hamiltonienne qui utilise [l](https://qiskit.github.io/qiskit-addon-aqc-tensor/) 'add-on AQC-Tensor Qiskit afin de mapper la description du problème à un circuit à profondeur réduite pour exécution sur le matériel.\n",
        "\n",
        "Si vous téléchargez cette page et que vous la consultez localement dans un éditeur de notes, vous verrez que certaines cellules de code contiennent la [commande magique ](https://ipython.readthedocs.io/en/stable/interactive/magics.html#cellmagic-writefile)`%%writefile`. Cette commande magique enregistre le code dans `./source_files/template_hamiltonian_simulation.py`, qui est le modèle de fonction que vous pouvez télécharger sur et exécuter à distance via Qiskit Serverless.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "115c14aa-5028-46f9-ab19-b49d47519636",
      "metadata": {},
      "source": [
        "<span id=\"collect-and-validate-the-inputs\" />\n",
        "\n",
        "### Collecter et valider les données saisies\n",
        "\n",
        "Commencez par obtenir les données nécessaires à l'élaboration du modèle. Cet exemple comporte des entrées spécifiques au domaine de la simulation hamiltonienne (telles que l'hamiltonien et l'observable) et des options spécifiques à la capacité (telles que le degré de compression des couches initiales du circuit de Trotter à l'aide d'AQC-Tensor, ou des options avancées pour affiner la suppression et l'atténuation des erreurs au-delà des valeurs par défaut qui font partie de cet exemple).\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": [
        "Lorsque le modèle de fonction est en cours d'exécution, il est utile de renvoyer des informations dans les journaux à l'aide des instructions print, afin de mieux évaluer la progression de la charge de travail. Voici un exemple simple d'impression du site `estimator_options` afin de conserver une trace des options utilisées par l'estimateur. Il existe de nombreux autres exemples similaires tout au long du programme pour signaler les progrès réalisés au cours de l'exécution, notamment la valeur de la fonction objective au cours de la composante itérative d'AQC-Tensor et la profondeur de deux qubits du circuit final de l'architecture d'ensemble d'instructions (ISA) destiné à être exécuté sur le matériel.\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",
        "#### Valider les entrées\n",
        "\n",
        "La validation des entrées est un aspect important pour garantir que le modèle peut être réutilisé pour toute une série d'entrées. Le code suivant est un exemple de vérification de la fidélité d'arrêt lors de l'utilisation de AQC-Tensor et, si ce n'est pas le cas, de renvoi d'un message d'erreur informatif sur la manière de corriger l'erreur.\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",
        "#### Préparez les sorties de la fonction\n",
        "\n",
        "Tout d'abord, préparez un dictionnaire qui contiendra toutes les sorties du modèle de fonction. Des clés seront ajoutées à ce dictionnaire tout au long du flux de travail, et il sera renvoyé à la fin du programme.\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",
        "### Cartographier le problème et prétraiter le circuit avec AQC\n",
        "\n",
        "L'optimisation de l'AQC-Tensor se fait à l'étape 1 d'un modèle Qiskit.  Tout d'abord, un état cible est construit.  Dans cet exemple, il est construit à partir d'un circuit cible qui évolue avec le même hamiltonien pendant la même période que la partie AQC.  Ensuite, un ansatz est généré à partir d'un circuit équivalent, mais avec moins d'étapes de Trotter.  Dans la partie principale de l'algorithme AQC, cet ansatz est itérativement rapproché de l'état cible.  Enfin, le résultat est combiné avec le reste des étapes de Trotter nécessaires pour atteindre le temps d'évolution souhaité.\n",
        "\n",
        "Notez les exemples supplémentaires de journalisation incorporés dans le code suivant.\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",
        "### Optimiser le circuit final pour l'exécution\n",
        "\n",
        "Après la partie AQC du flux de travail, le site `final_circuit` est [transpilé pour le matériel](/docs/guides/transpile#instruction-set-architecture) comme d'habitude.\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",
        "#### Quittez rapidement si vous utilisez le mode simulation\n",
        "\n",
        "Si le mode de fonctionnement à sec a été sélectionné, le programme est arrêté avant d'être exécuté sur le matériel. Cela peut être utile si, par exemple, vous voulez d'abord inspecter la profondeur de deux qubits du circuit ISA avant de décider de l'exécuter sur le matériel.\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",
        "#### Exécuter le circuit sur le matériel\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",
        "#### Enregistrer la sortie\n",
        "\n",
        "Ce modèle de fonction renvoie les résultats pertinents au niveau du domaine pour ce flux de travail de simulation hamiltonienne (valeurs d'attente) en plus des métadonnées importantes générées en cours de route.\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",
        "## Déployez la fonction sur IBM Quantum Platform\n",
        "\n",
        "La section précédente a permis de créer un programme à exécuter à distance. Le code de cette section télécharge ce programme vers Qiskit Serverless.\n",
        "\n",
        "Utilisez `qiskit-ibm-catalog` pour vous authentifier sur `QiskitServerless` avec votre clé API, que vous trouverez sur le tableau de bord de [IBM Quantum Platform](), et téléchargez le programme.\n",
        "\n",
        "Vous pouvez éventuellement utiliser `save_account()` pour enregistrer vos identifiants (voir le guide [Configurer votre compte IBM Cloud](/docs/guides/cloud-setup#cloud-save) ). Notez que cela écrit vos informations d'identification dans le même fichier que [`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": [
        "Ce programme a des dépendances personnalisées `pip` .  Ajoutez-les à un tableau `dependencies` lors de la construction de l'instance `QiskitFunction` :\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": [
        "Enfin, pour vérifier si le programme a été téléchargé avec succès, utilisez `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",
        "## Exécuter le modèle de fonction à distance\n",
        "\n",
        "Le modèle de fonction a été téléchargé, vous pouvez donc l'exécuter à distance avec Qiskit Serverless. Tout d'abord, chargez le modèle par son nom :\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": [
        "Ensuite, exécutez le modèle avec les données d'entrée du domaine pour la simulation hamiltonienne. Cet exemple spécifie un modèle XXZ à 50 qubits avec des couplages aléatoires, un état initial et une observable.\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": [
        "Vérifier l'état du travail :\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": [
        "Une fois le travail exécuté, vous pouvez récupérer les journaux créés à partir des sorties `print()` . Ceux-ci peuvent fournir des informations exploitables sur l'état d'avancement de la simulation hamiltonienne. Par exemple, la valeur de la fonction objective pendant la composante itérative de l'AQC, ou la profondeur de deux qubits du circuit ISA final destiné à être exécuté sur le matériel.\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": [
        "Bloquer le reste du programme jusqu'à ce qu'un résultat soit disponible. Une fois le travail effectué, vous pouvez récupérer les résultats. Il s'agit notamment du résultat de la simulation hamiltonienne au niveau du domaine (valeur d'espérance) et de métadonnées utiles.\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": [
        "Une fois le travail terminé, l'ensemble de la sortie de la journalisation sera disponible.\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",
        "## Etapes suivantes\n",
        "\n",
        "<Admonition type=\"info\" title=\"Recommandations\">\n",
        "  Pour en savoir plus sur l'addon Qiskit AQC-Tensor, consultez le tutoriel [Improved Trotterized Time Evolution with Approximate Quantum Compilation](/docs/tutorials/approximate-quantum-compilation-for-time-evolution) ou le [dépôt 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=\"**Code source complet du programme**\">\n",
        "    Voici la source complète de `./source_files/template_hamiltonian_simulation.py` sous la forme d'un bloc de code.\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
}