{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "b9fd7c5e-f3b8-4f0d-8632-821d601af52c",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Eseguire lavori in una sessione\"\n",
        "description: \"Come eseguire un processo di calcolo quantistico in una sessione di Compute Service di IBM Quantum.\"\n",
        "---\n",
        "\n",
        "<span id=\"run-jobs-in-a-session\" />\n",
        "\n",
        "# Eseguire lavori in una sessione\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "817c70e7-29dd-4f70-85ad-6487d7c4b010",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "{/*\n",
        "  DO NOT EDIT THIS CELL!!!\n",
        "  This cell's content is generated automatically by a script. Anything you add\n",
        "  here will be removed next time the notebook is run. To add new content, create\n",
        "  a new cell before or after this one.\n",
        "  */}\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Versioni del pacchetto\">\n",
        "    Il codice presente in questa pagina è stato sviluppato utilizzando i seguenti requisiti.\n",
        "    Si consiglia di utilizzare queste versioni o versioni più recenti.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.3.1\n",
        "    qiskit-ibm-runtime~=0.45.0\n",
        "    scipy~=1.17.1\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "be06e0ee-e593-4fe7-aa98-4f6e0dcbaa9f",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\" title=\"Nota\">\n",
        "  Gli utenti di Open Plan non possono inviare lavori di sessione. I carichi di lavoro devono essere eseguiti in [modalità lavoro](/docs/guides/execution-modes#job-mode) o in [modalità batch](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n",
        "Utilizzate le sessioni quando avete bisogno di un accesso dedicato ed esclusivo alla QPU.\n",
        "\n",
        "<span id=\"set-up-to-use-sessions\" />\n",
        "\n",
        "## Configurazione per l'utilizzo delle sessioni\n",
        "\n",
        "Prima di avviare una sessione, è necessario [configurare il client Compute di IBM Quantum](/docs/guides/install-qiskit-runtime) e inizializzarlo come servizio:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "117d0471-1f98-489c-906f-8aab836cd877",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime import (\n",
        "    QiskitRuntimeService,\n",
        "    Session,\n",
        "    SamplerV2 as Sampler,\n",
        "    EstimatorV2 as Estimator,\n",
        "    Executor,\n",
        ")\n",
        "\n",
        "service = QiskitRuntimeService()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1e1cd9a3-7f36-4f42-8924-7f4dac202788",
      "metadata": {},
      "source": [
        "<span id=\"open-a-session\" />\n",
        "\n",
        "## Apri una sessione\n",
        "\n",
        "È possibile aprire una sessione di runtime utilizzando il gestore di contesto `with Session(...)` o inizializzando la classe `Session` classe. Quando si avvia una sessione, è necessario specificare una QPU passando un oggetto `backend` . La sessione inizia quando inizia l'esecuzione del primo lavoro.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Se si apre una sessione ma non vi si inviano lavori per 30 minuti, la sessione si chiude automaticamente.\n",
        "</Admonition>\n",
        "\n",
        "**Classe di sessione**\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  Il seguente blocco di codice restituisce un errore per gli utenti di Open Plan perché utilizza le sessioni. I carichi di lavoro su Open Plan possono essere eseguiti solo in [modalità job](/docs/guides/execution-modes#job-mode) o [batch](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "2694bd4c-2011-4671-9625-3e7e941dd381",
      "metadata": {},
      "outputs": [],
      "source": [
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "session = Session(backend=backend)\n",
        "estimator = Estimator(mode=session)\n",
        "sampler = Sampler(mode=session)\n",
        "executor = Executor(mode=session)\n",
        "# Close the session because no context manager was used.\n",
        "session.close()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e0460f64-f5a8-4663-834a-a4c15c9ad82b",
      "metadata": {},
      "source": [
        "**Gestore del contesto**\n",
        "\n",
        "Il gestore del contesto apre e chiude automaticamente la sessione.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  Il seguente blocco di codice restituisce un errore per gli utenti di Open Plan perché utilizza le sessioni. I carichi di lavoro su Open Plan possono essere eseguiti solo in [modalità job](/docs/guides/execution-modes#job-mode) o [batch](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "192e5e57-2f9d-4f8e-b3e7-1dd31907e8a6",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime import (\n",
        "    Session,\n",
        "    SamplerV2 as Sampler,\n",
        "    EstimatorV2 as Estimator,\n",
        "    Executor,\n",
        ")\n",
        "\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "with Session(backend=backend):\n",
        "    estimator = Estimator()\n",
        "    sampler = Sampler()\n",
        "    executor = Executor()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e4219769-6348-4d0c-8e13-830177a4e7b8",
      "metadata": {},
      "source": [
        "<span id=\"specify-length\" />\n",
        "\n",
        "<span id=\"session-length\" />\n",
        "\n",
        "## Durata delle sessioni\n",
        "\n",
        "Il tempo massimo di vita della sessione (TTL) determina la durata della sessione.  È possibile impostare questo valore con il parametro `max_time` . Questo dovrebbe superare il tempo di esecuzione del lavoro più lungo.\n",
        "\n",
        "Questo timer si avvia all'avvio della sessione.  Quando il valore viene raggiunto, la sessione viene chiusa.  I lavori in corso vengono terminati, mentre quelli ancora in coda non vengono eseguiti.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  Il seguente blocco di codice restituisce un errore per gli utenti di Open Plan perché utilizza le sessioni. I carichi di lavoro su Open Plan possono essere eseguiti solo in [modalità job](/docs/guides/execution-modes#job-mode) o [batch](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n",
        "```python\n",
        "with Session(backend=backend, max_time=\"25m\"):\n",
        "  ...\n",
        "```\n",
        "\n",
        "Esiste anche un valore di time to live interattivo (interactive TTL) che non può essere configurato.  Se non vengono accodati lavori di sessione entro tale finestra, la sessione viene temporaneamente disattivata.\n",
        "\n",
        "Valori predefiniti:\n",
        "\n",
        "| Tipo di istanza (Piano Open o Premium)                                                           | TTL interattivo | TTL massimo |\n",
        "| ------------------------------------------------------------------------------------------------ | --------------- | ----------- |\n",
        "| Piano Premium                                                                                    | 60 sec          | 8 h\\*       |\n",
        "| *\\* Alcune istanze del Piano Premium potrebbero essere configurate per avere un valore diverso.* |                 |             |\n",
        "\n",
        "Per determinare il TTL massimo o interattivo di una sessione, seguire le istruzioni in [Determinare i dettagli della sessione](#session-details) e cercare il valore `max_time`o `interactive_timeout` , rispettivamente.\n",
        "\n",
        "<span id=\"ends\" />\n",
        "\n",
        "<span id=\"end-a-session\" />\n",
        "\n",
        "## Termina una sessione\n",
        "\n",
        "Una sessione termina nelle seguenti circostanze:\n",
        "\n",
        "* Il raggiungimento del valore massimo di timeout (TTL) comporta l'annullamento di tutti i lavori in coda.\n",
        "* La sessione viene annullata manualmente, con conseguente cancellazione di tutti i lavori in coda.\n",
        "* La sessione viene chiusa manualmente.  La sessione smette di accettare nuovi lavori, ma continua a eseguire i lavori in coda con priorità.\n",
        "* Se si usa Session come gestore del contesto, cioè `with Session()`, la sessione viene chiusa automaticamente quando il contesto termina (lo stesso comportamento di `session.close()`).\n",
        "\n",
        "<span id=\"close\" />\n",
        "\n",
        "<span id=\"close-a-session\" />\n",
        "\n",
        "### Chiudi una sessione\n",
        "\n",
        "Una sessione si chiude automaticamente quando si esce dal gestore del contesto. Quando si esce dal gestore del contesto di sessione, la sessione viene posta nello stato \"In corso, non accetta nuovi lavori\". Ciò significa che la sessione termina l'elaborazione di tutti i lavori in corso o in coda fino al raggiungimento del valore massimo di timeout. Al termine di tutti i lavori, la sessione viene immediatamente chiusa. Ciò consente allo scheduler di eseguire il lavoro successivo senza attendere il timeout interattivo della sessione, riducendo così il tempo medio di accodamento dei lavori. Non è possibile presentare lavori in una sessione chiusa.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  Il seguente blocco di codice restituisce un errore per gli utenti di Open Plan perché utilizza le sessioni. I carichi di lavoro su Open Plan possono essere eseguiti solo in [modalità job](/docs/guides/execution-modes#job-mode) o [batch](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "c6646bed-3064-488f-b2ff-da9ba793775a",
      "metadata": {},
      "outputs": [],
      "source": [
        "with Session(backend=backend) as session:\n",
        "    estimator = Estimator()\n",
        "    sampler = Sampler()\n",
        "    job1 = estimator.run([estimator_pub])\n",
        "    job2 = sampler.run([sampler_pub])\n",
        "\n",
        "# The session is no longer accepting jobs but the submitted job will run to completion.\n",
        "result = job1.result()\n",
        "result2 = job2.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "20eb23f3-fc34-4f38-8ad7-85278ff4c823",
      "metadata": {},
      "source": [
        "<Admonition type=\"tip\">\n",
        "  Se non si utilizza un gestore di contesto, chiudere manualmente la sessione per evitare costi indesiderati. È possibile chiudere una sessione non appena si è finito di inviarle lavori. Quando una sessione viene chiusa con `session.close()`, non accetta più nuovi lavori, ma i lavori già inviati continuano a essere eseguiti fino al completamento e i loro risultati possono essere recuperati.\n",
        "</Admonition>\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  Il seguente blocco di codice restituisce un errore per gli utenti di Open Plan perché utilizza le sessioni. I carichi di lavoro su Open Plan possono essere eseguiti solo in [modalità job](/docs/guides/execution-modes#job-mode) o [batch](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "861cf6b3-9695-41eb-9d3d-d5293880ca75",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Result1: PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(3, 2), dtype=float64>), stds=np.ndarray(<shape=(3, 2), dtype=float64>), ensemble_standard_error=np.ndarray(<shape=(3, 2), dtype=float64>), shape=(3, 2)), metadata={'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32})], metadata={'dynamical_decoupling': {'enable': False, 'sequence_type': 'XX', 'extra_slack_distribution': 'middle', 'scheduling_method': 'alap'}, 'twirling': {'enable_gates': False, 'enable_measure': True, 'num_randomizations': 'auto', 'shots_per_randomization': 'auto', 'interleave_randomizations': True, 'strategy': 'active-accum'}, 'resilience': {'measure_mitigation': True, 'zne_mitigation': False, 'pec_mitigation': False}, 'version': 2})\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Result2: PrimitiveResult([SamplerPubResult(data=DataBin(meas=BitArray(<shape=(3, 2), num_shots=4096, num_bits=2>), meas0=BitArray(<shape=(3, 2), num_shots=4096, num_bits=156>), shape=(3, 2)), metadata={'circuit_metadata': {}})], metadata={'execution': {'execution_spans': ExecutionSpans([DoubleSliceSpan(<start='2026-03-15 07:33:44', stop='2026-03-15 07:33:51', size=24576>)])}, 'version': 2})\n"
          ]
        }
      ],
      "source": [
        "session = Session(backend=backend)\n",
        "\n",
        "# If using qiskit-ibm-runtime earlier than 0.24.0, change `mode=` to `session=`\n",
        "estimator = Estimator(mode=session)\n",
        "sampler = Sampler(mode=session)\n",
        "job1 = estimator.run([estimator_pub])\n",
        "job2 = sampler.run([sampler_pub])\n",
        "print(f\"Result1: {job1.result()}\")\n",
        "print(f\"Result2: {job2.result()}\")\n",
        "\n",
        "# Manually close the session. Running and queued jobs will run to completion.\n",
        "session.close()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "aad804ed-027f-49c3-9f7d-8851a4f3de3a",
      "metadata": {},
      "source": [
        "<span id=\"session-status\" />\n",
        "\n",
        "<span id=\"check-session-status\" />\n",
        "\n",
        "## Controlla lo stato della sessione\n",
        "\n",
        "È possibile interrogare lo stato di una sessione per comprenderne lo stato attuale utilizzando `session.status()` o visualizzando la pagina dei [carichi di lavoro](/workloads).\n",
        "\n",
        "Lo stato della sessione può essere uno dei seguenti:\n",
        "\n",
        "* `Pending`: La sessione non è stata avviata o è stata disattivata. Il lavoro di sessione successivo deve attendere in coda come gli altri lavori.\n",
        "* `In progress, accepting new jobs`: La sessione è attiva e accetta nuovi lavori.\n",
        "* `In progress, not accepting new jobs`: La sessione è attiva ma non accetta nuovi lavori. L'invio di lavori alla sessione viene rifiutato, ma i lavori di sessione in sospeso vengono eseguiti fino al completamento. La sessione viene chiusa automaticamente al termine di tutti i lavori.\n",
        "* `Closed`: Il valore massimo di timeout della sessione è stato raggiunto o la sessione è stata chiusa esplicitamente.\n",
        "\n",
        "<span id=\"session-details\" />\n",
        "\n",
        "<span id=\"determine-session-details\" />\n",
        "\n",
        "## Determinare i dettagli della sessione\n",
        "\n",
        "Per una panoramica completa della configurazione e dello stato di una sessione, utilizzare il sito `session.details() method`.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  Il seguente blocco di codice restituisce un errore per gli utenti di Open Plan perché utilizza le sessioni. I carichi di lavoro su Open Plan possono essere eseguiti solo in [modalità job](/docs/guides/execution-modes#job-mode) o [batch](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "82a2599e-3e32-4e01-9a36-b77a56af7647",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "{'id': 'a9fd2f9d-6239-4451-a19c-9b45aa6a0618', 'backend_name': 'ibm_torino', 'interactive_timeout': 60, 'max_time': 28800, 'active_timeout': 28800, 'state': 'open', 'accepting_jobs': True, 'last_job_started': None, 'last_job_completed': None, 'started_at': None, 'closed_at': None, 'activated_at': None, 'mode': 'dedicated', 'usage_time': None}\n"
          ]
        }
      ],
      "source": [
        "from qiskit_ibm_runtime import (\n",
        "    QiskitRuntimeService,\n",
        "    Session,\n",
        "    EstimatorV2 as Estimator,\n",
        ")\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "\n",
        "with Session(backend=backend) as session:\n",
        "    print(session.details())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7db97311-25cb-4b81-9dba-494264c554c6",
      "metadata": {},
      "source": [
        "<span id=\"usage-patterns\" />\n",
        "\n",
        "## Modelli di utilizzo\n",
        "\n",
        "Le sessioni sono particolarmente utili per gli algoritmi che richiedono una comunicazione frequente tra risorse classiche e quantistiche.\n",
        "\n",
        "Esempio: Eseguire un carico di lavoro iterativo che utilizza il classico ottimizzatore SciPy per minimizzare una funzione di costo. In questo modello, SciPy utilizza l'output della funzione di costo per calcolare il suo prossimo input.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  Il seguente blocco di codice restituisce un errore per gli utenti di Open Plan perché utilizza le sessioni. I carichi di lavoro su Open Plan possono essere eseguiti solo in [modalità job](/docs/guides/execution-modes#job-mode) o [batch](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "77cc7c96-e8c0-4970-b05e-361ddf74d707",
      "metadata": {},
      "outputs": [],
      "source": [
        "from scipy.optimize import minimize\n",
        "from qiskit.circuit.library import efficient_su2\n",
        "\n",
        "\n",
        "def cost_func(params, ansatz, hamiltonian, estimator):\n",
        "    # Return estimate of energy from estimator\n",
        "\n",
        "    energy = sum(\n",
        "        estimator.run([(ansatz, hamiltonian, params)]).result()[0].data.evs\n",
        "    )\n",
        "    return energy\n",
        "\n",
        "\n",
        "hamiltonian = SparsePauliOp.from_list(\n",
        "    [(\"YZ\", 0.3980), (\"ZI\", -0.3980), (\"ZZ\", -0.0113), (\"XX\", 0.1810)]\n",
        ")\n",
        "su2_ansatz = efficient_su2(hamiltonian.num_qubits)\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
        "ansatz = pm.run(su2_ansatz)\n",
        "mapped_hamiltonian = [\n",
        "    operator.apply_layout(ansatz.layout) for operator in hamiltonian\n",
        "]\n",
        "\n",
        "num_params = ansatz.num_parameters\n",
        "x0 = 2 * np.pi * np.random.random(num_params)\n",
        "\n",
        "session = Session(backend=backend)\n",
        "\n",
        "\n",
        "# If using qiskit-ibm-runtime earlier than 0.24.0, change `mode=` to `session=`\n",
        "estimator = Estimator(mode=session, options={\"default_shots\": int(1e4)})\n",
        "res = minimize(\n",
        "    cost_func,\n",
        "    x0,\n",
        "    args=(ansatz, mapped_hamiltonian, estimator),\n",
        "    method=\"cobyla\",\n",
        "    options={\"maxiter\": 25},\n",
        ")\n",
        "\n",
        "# Close the session because no context manager was used.\n",
        "session.close()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8c03c721-f040-4066-a9d2-f2dd39777789",
      "metadata": {},
      "source": [
        "<span id=\"two-vqe\" />\n",
        "\n",
        "<span id=\"run-two-vqe-algorithms-in-a-session-by-using-threading\" />\n",
        "\n",
        "## Esegui due algoritmi VQE in una sessione utilizzando il threading\n",
        "\n",
        "È possibile ottenere di più da una sessione eseguendo più carichi di lavoro contemporaneamente. L'esempio seguente mostra come sia possibile eseguire contemporaneamente due algoritmi VQE, ciascuno dei quali utilizza un diverso ottimizzatore classico, all'interno di una singola sessione. I tag dei lavori vengono utilizzati anche per differenziare i lavori da ciascun carico di lavoro.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  Il seguente blocco di codice restituisce un errore per gli utenti di Open Plan perché utilizza le sessioni. I carichi di lavoro su Open Plan possono essere eseguiti solo in [modalità job](/docs/guides/execution-modes#job-mode) o [batch](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "e83f7d60-13f0-4df1-9766-6fa67c970362",
      "metadata": {},
      "outputs": [],
      "source": [
        "from concurrent.futures import ThreadPoolExecutor\n",
        "from qiskit_ibm_runtime import EstimatorV2 as Estimator\n",
        "\n",
        "\n",
        "def minimize_thread(estimator, method):\n",
        "    return minimize(\n",
        "        cost_func,\n",
        "        x0,\n",
        "        args=(ansatz, mapped_hamiltonian, estimator),\n",
        "        method=method,\n",
        "        options={\"maxiter\": 25},\n",
        "    )\n",
        "\n",
        "\n",
        "with Session(backend=backend), ThreadPoolExecutor() as executor:\n",
        "    estimator1 = Estimator()\n",
        "    estimator2 = Estimator()\n",
        "\n",
        "    # Use different tags to differentiate the jobs.\n",
        "    estimator1.options.environment.job_tags = [\"cobyla\"]\n",
        "    estimator2.options.environment.job_tags = [\"nelder-mead\"]\n",
        "\n",
        "    # Submit the two workloads.\n",
        "    cobyla_future = executor.submit(minimize_thread, estimator1, \"cobyla\")\n",
        "    nelder_mead_future = executor.submit(\n",
        "        minimize_thread, estimator2, \"nelder-mead\"\n",
        "    )\n",
        "\n",
        "    # Get workload results.\n",
        "    cobyla_result = cobyla_future.result()\n",
        "    nelder_mead_result = nelder_mead_future.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0194fb4b-0917-45d7-aeb1-9fdff38cc5c5",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Passi successivi\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Suggerimenti\">\n",
        "  * Provate un esempio nel tutorial sull' [algoritmo di ottimizzazione approssimativa quantistica (QAOA)](/docs/tutorials/quantum-approximate-optimization-algorithm).\n",
        "  * Esaminare il riferimento all' [API Session](/docs/api/qiskit-ibm-runtime/session).\n",
        "  * Comprendere i [limiti del lavoro](/docs/guides/job-limits) quando si invia un lavoro a una QPU IBM®.\n",
        "  * [Leggi le domande frequenti sulle modalità di esecuzione](/docs/guides/execution-modes-faq) delle revisioni.\n",
        "</Admonition>\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
}