{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "b3e994de-6477-421d-8a9a-6b20d45260ae",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Creare un modello di funzione Qiskit per la simulazione hamiltoniana\"\n",
        "description: \"Come creare un programma di transpilazione parallelo e distribuirlo su IBM Quantum Platform per utilizzarlo come servizio remoto riutilizzabile.\"\n",
        "---\n",
        "\n",
        "<span id=\"build-a-qiskit-function-template-for-hamiltonian-simulation\" />\n",
        "\n",
        "# Creare un modello di funzione Qiskit per la simulazione hamiltoniana\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": [
        "Questo modello racchiude un flusso di lavoro per simulare l'evoluzione temporale di uno stato iniziale rispetto a un hamiltoniano basato sullo spin definito dall'utente e restituisce una serie di valori attesi specificati utilizzando l'add-on [AQC-Tensor](https://qiskit.github.io/qiskit-addon-aqc-tensor/) Qiskit.\n",
        "\n",
        "Questo modello è strutturato come un modello Qiskit con i seguenti passaggi:\n",
        "\n",
        "<span id=\"1-collecting-input-and-mapping-the-problem\" />\n",
        "\n",
        "#### 1. Raccolta di input e mappatura del problema\n",
        "\n",
        "Questa sezione prende in input l'hamiltoniana da simulare, uno stato iniziale sotto forma di `QuantumCircuit`, un insieme di osservabili per stimare i valori di aspettativa e una specifica di opzioni per l'addon AQC. Questa fase convalida la presenza di tutti i dati di input richiesti e il loro formato corretto.\n",
        "\n",
        "Gli argomenti in ingresso vengono quindi utilizzati per costruire i circuiti quantistici e gli operatori rilevanti per il flusso di lavoro. Si crea un circuito di destinazione e si trova una rappresentazione di stato del prodotto matriciale di questo circuito utilizzando l'addon AQC. In seguito, viene generato un circuito di ansatz e ottimizzato con metodi di rete tensoriale, producendo un circuito finale che esegue il resto dell'evoluzione temporale.\n",
        "\n",
        "<span id=\"2-prepare-the-generated-circuits-for-execution\" />\n",
        "\n",
        "#### 2. Preparare i circuiti generati per l'esecuzione\n",
        "\n",
        "I circuiti generati dall'addon AQC vengono poi transpilati per essere eseguiti su un backend scelto. Viene creata un'istanza [`EstimatorV2`](../api/qiskit-ibm-runtime/estimator-v2) viene creata con un insieme predefinito di opzioni di attenuazione degli errori per gestire l'esecuzione del circuito.\n",
        "\n",
        "<span id=\"3-execution\" />\n",
        "\n",
        "#### 3. Esecuzione\n",
        "\n",
        "Infine, il circuito di ansatz viene transpilato ed eseguito su una QPU e raccoglie le stime per tutti i valori di aspettativa specificati, che vengono restituiti in un formato serializzabile per l'accesso da parte dell'utente.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e451f954-1d8f-4687-a7e9-e4b0dfa170f3",
      "metadata": {},
      "source": [
        "<span id=\"write-the-function-template\" />\n",
        "\n",
        "## Scrivi il modello di funzione\n",
        "\n",
        "In primo luogo, scrivere un modello di funzione per la simulazione hamiltoniana che utilizzi [l](https://qiskit.github.io/qiskit-addon-aqc-tensor/) 'add-on AQC-Tensor Qiskit per mappare la descrizione del problema su un circuito a profondità ridotta per l'esecuzione su hardware.\n",
        "\n",
        "Se scarichi questa pagina e la visualizzi in locale in un editor di file di testo, noterai che alcune delle celle di codice contengono il [comando magico ](https://ipython.readthedocs.io/en/stable/interactive/magics.html#cellmagic-writefile)`%%writefile`. Questo comando magico salva il codice in `./source_files/template_hamiltonian_simulation.py`, ovvero il modello di funzione che puoi caricare su ed eseguire in remoto tramite Qiskit Serverless.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "115c14aa-5028-46f9-ab19-b49d47519636",
      "metadata": {},
      "source": [
        "<span id=\"collect-and-validate-the-inputs\" />\n",
        "\n",
        "### Raccogliere e convalidare gli input\n",
        "\n",
        "Iniziate con l'ottenere gli input per il modello. Questo esempio ha input specifici del dominio rilevanti per la simulazione hamiltoniana (come l'hamiltoniano e l'osservabile) e opzioni specifiche della capacità (come la quantità di compressione degli strati iniziali del circuito di Trotter usando AQC-Tensor, o opzioni avanzate per la regolazione fine della soppressione e della mitigazione degli errori al di là dei valori predefiniti che fanno parte di questo esempio).\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": [
        "Quando il modello di funzione è in esecuzione, è utile riportare le informazioni nei log utilizzando le istruzioni di stampa, in modo da poter valutare meglio l'andamento del carico di lavoro. Di seguito è riportato un semplice esempio di stampa del sito `estimator_options` , in modo da avere una registrazione delle opzioni dell'Estimatore effettivamente utilizzate. Ci sono molti altri esempi simili in tutto il programma per segnalare i progressi durante l'esecuzione, tra cui il valore della funzione obiettivo durante la componente iterativa di AQC-Tensor e la profondità di due qubit del circuito finale dell'instruction set architecture (ISA) destinato all'esecuzione su hardware.\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",
        "#### Convalida gli input\n",
        "\n",
        "Un aspetto importante per garantire che il modello possa essere riutilizzato per una serie di input è la convalida dell'input. Il codice seguente è un esempio di verifica che la fedeltà di arresto durante AQC-Tensor sia stata specificata in modo appropriato e, in caso contrario, restituisce un messaggio di errore informativo su come risolvere l'errore.\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",
        "#### Preparare gli output della funzione\n",
        "\n",
        "Per prima cosa, preparare un dizionario che contenga tutti gli output dei modelli di funzione. Le chiavi verranno aggiunte a questo dizionario nel corso del flusso di lavoro e verrà restituito alla fine del programma.\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",
        "### Mappare il problema ed eseguire la pre-elaborazione del circuito con AQC\n",
        "\n",
        "L'ottimizzazione di AQC-Tensor avviene nel passo 1 di un modello Qiskit.  In primo luogo, viene costruito uno stato di destinazione.  In questo esempio, è costruito a partire da un circuito target che evolve la stessa hamiltoniana per lo stesso periodo di tempo della parte AQC.  Quindi, si genera un'ansatz da un circuito equivalente, ma con meno passi di Trotter.  Nella parte principale dell'algoritmo AQC, tale ansatz viene avvicinato iterativamente allo stato target.  Infine, il risultato viene combinato con il resto dei passi di Trotter necessari per raggiungere il tempo di evoluzione desiderato.\n",
        "\n",
        "Si notino gli esempi aggiuntivi di registrazione incorporati nel codice seguente.\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",
        "### Ottimizzare il circuito finale per l'esecuzione\n",
        "\n",
        "Dopo la parte AQC del flusso di lavoro, `final_circuit` viene [transpilato per l'hardware](/docs/guides/transpile#instruction-set-architecture) come di consueto.\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",
        "#### Esci prima se utilizzi la modalità dry run\n",
        "\n",
        "Se è stata selezionata la modalità Dry Run, il programma viene interrotto prima di essere eseguito sull'hardware. Questo può essere utile se, ad esempio, si vuole prima ispezionare la profondità a due qubit del circuito ISA prima di decidere di eseguirlo sull'hardware.\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",
        "#### Eseguire il circuito sull'hardware\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",
        "#### Salva l'output\n",
        "\n",
        "Questo modello di funzione restituisce l'output rilevante a livello di dominio per questo flusso di lavoro di simulazione hamiltoniana (valori di aspettativa), oltre a importanti metadati generati lungo il percorso.\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",
        "## Distribuisci la funzione su IBM Quantum Platform\n",
        "\n",
        "Nella sezione precedente è stato creato un programma da eseguire in remoto. Il codice in questa sezione carica il programma su Qiskit Serverless.\n",
        "\n",
        "Utilizzate `qiskit-ibm-catalog` per autenticarvi su `QiskitServerless` con la vostra chiave API, che potete trovare sulla dashboard di [IBM Quantum Platform](), e caricate il programma.\n",
        "\n",
        "È possibile utilizzare `save_account()` per salvare le credenziali (vedere la guida [Configurazione dell'account IBM Cloud](/docs/guides/cloud-setup#cloud-save) ). Si noti che questa operazione scrive le credenziali nello stesso file di [`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": [
        "Questo programma ha dipendenze personalizzate da `pip` .  Aggiungerli a un array `dependencies` quando si costruisce l'istanza `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": [
        "Infine, per verificare se il programma è stato caricato con successo, utilizzare `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",
        "## Esegui il modello di funzione in remoto\n",
        "\n",
        "Il modello di funzione è stato caricato, quindi è possibile eseguirlo in remoto con Qiskit Serverless. Per prima cosa, caricare il modello per nome:\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": [
        "Quindi, eseguire il modello con gli input a livello di dominio per la simulazione hamiltoniana. Questo esempio specifica un modello XXZ a 50 qubit con accoppiamenti casuali e uno stato e un'osservabile iniziali.\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": [
        "Controllare lo stato del lavoro:\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": [
        "Dopo l'esecuzione del lavoro, è possibile recuperare i registri creati dalle uscite di `print()` . Questi possono fornire informazioni utili sull'avanzamento del flusso di lavoro della simulazione hamiltoniana. Ad esempio, il valore della funzione obiettivo durante la componente iterativa del CQA, o la profondità di due qubit del circuito ISA finale destinato all'esecuzione su hardware.\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": [
        "Blocca il resto del programma finché non è disponibile un risultato. Al termine del lavoro, è possibile recuperare i risultati. Questi includono l'output a livello di dominio della simulazione hamiltoniana (valore di aspettativa) e metadati utili.\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": [
        "Al termine del lavoro, sarà disponibile l'intero output di registrazione.\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",
        "## Passi successivi\n",
        "\n",
        "<Admonition type=\"info\" title=\"Suggerimenti\">\n",
        "  Per un'immersione più approfondita nell'addon Qiskit AQC-Tensor, consultate il tutorial [Improved Trotterized Time Evolution with Approximate Quantum Compilation](/docs/tutorials/approximate-quantum-compilation-for-time-evolution) o il [repository 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=\"**Codice sorgente completo del programma**\">\n",
        "    Ecco l'intero sorgente di `./source_files/template_hamiltonian_simulation.py` come blocco di codice.\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
}