{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "f4e55284-8bd6-4cb2-b044-11816cba1e2d",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Ejecutar trabajos por lotes\"\n",
        "description: \"Cómo ejecutar trabajos de computación cuántica en modo por lotes utilizando Qiskit Runtime.\"\n",
        "---\n",
        "\n",
        "<span id=\"run-jobs-in-a-batch\" />\n",
        "\n",
        "# Ejecutar trabajos por lotes\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3f77b9f7-7967-45ad-a68b-3db6e0d36456",
      "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=\"Versiones del paquete\">\n",
        "    El código de esta página se ha desarrollado siguiendo los siguientes requisitos.\n",
        "    Recomendamos utilizar estas versiones o posteriores.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.3.0\n",
        "    qiskit-ibm-runtime~=0.43.1\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "388d0a36-0a7c-4b60-8607-4e535f8adf2c",
      "metadata": {},
      "source": [
        "Utilice el modo por lotes para enviar varios trabajos primitivos simultáneamente. A continuación se ofrecen ejemplos de trabajo con lotes.\n",
        "\n",
        "<span id=\"set-up-to-use-batches\" />\n",
        "\n",
        "## Configurar para usar lotes\n",
        "\n",
        "Antes de iniciar un lote, debe [configurar Qiskit Runtime](/docs/guides/install-qiskit) e inicializarlo como servicio:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "340d9d45-9ec0-473f-bf17-9dc7eb0804ed",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime import (\n",
        "    QiskitRuntimeService,\n",
        "    Batch,\n",
        "    SamplerV2 as Sampler,\n",
        "    EstimatorV2 as Estimator,\n",
        "    Executor,\n",
        ")\n",
        "\n",
        "\n",
        "service = QiskitRuntimeService()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fc80a9fa-ffc1-419f-be98-ef36b73eda9a",
      "metadata": {},
      "source": [
        "<span id=\"open-a-batch\" />\n",
        "\n",
        "## Abrir un lote\n",
        "\n",
        "Puede abrir un lote en tiempo de ejecución utilizando el gestor de contexto `with Batch(...)` o inicializando la clase `Batch` clase Al iniciar un lote, debe especificar una QPU pasando un objeto `backend` .  El lote se inicia cuando comienza la ejecución de su primer trabajo.\n",
        "\n",
        "**Clase de lote**\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "02e53d53-3410-4e07-9c02-c582b97e15e1",
      "metadata": {},
      "outputs": [],
      "source": [
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "batch = Batch(backend=backend)\n",
        "estimator = Estimator(mode=batch)\n",
        "sampler = Sampler(mode=batch)\n",
        "executor = Executor(mode=batch)\n",
        "# Close the batch because no context manager was used.\n",
        "batch.close()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ad0927c2-cbba-4392-bced-fddcde738521",
      "metadata": {},
      "source": [
        "**Gestor de contexto**\n",
        "\n",
        "El gestor contextual abre y cierra automáticamente el lote.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "fe96e5dd-8237-458d-8657-dd0f71c65f8a",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime import (\n",
        "    Batch,\n",
        "    SamplerV2 as Sampler,\n",
        "    EstimatorV2 as Estimator,\n",
        "    Executor,\n",
        ")\n",
        "\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "with Batch(backend=backend):\n",
        "    estimator = Estimator()\n",
        "    sampler = Sampler()\n",
        "    executor = Executor()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "285f7538-3abd-4940-bca1-b1a61bc25bd5",
      "metadata": {},
      "source": [
        "<span id=\"specify-batch-length\" />\n",
        "\n",
        "<span id=\"batch-length\" />\n",
        "\n",
        "## Longitud del lote\n",
        "\n",
        "Puede definir el tiempo máximo de vida (TTL) del lote con el parámetro `max_time` . Esto debería superar el tiempo de ejecución del trabajo más largo. Este temporizador se inicia cuando comienza el lote.  Cuando se alcanza el valor, se cierra el lote.  Los trabajos que se estén ejecutando finalizarán, pero los trabajos que sigan en cola fallarán.\n",
        "\n",
        "```python\n",
        "with Batch(backend=backend, max_time=\"25m\"):\n",
        "  ...\n",
        "```\n",
        "\n",
        "También hay un valor de tiempo de vida interactivo (TTL interactivo) que no se puede configurar (1 minuto para todos los planes).  Si no hay trabajos por lotes en cola dentro de esa ventana, el lote se desactiva temporalmente.\n",
        "\n",
        "Valores TTL máximos por defecto:\n",
        "\n",
        "| Tipo de instancia        | TTL máximo predeterminado |\n",
        "| ------------------------ | ------------------------- |\n",
        "| Todos los planes de pago | 8 horas                   |\n",
        "| Abrir                    | 10 minutos                |\n",
        "\n",
        "Para determinar el TTL máximo o el TTL interactivo de un lote, siga las instrucciones de [Determinar detalles del lote](#batch-details) y busque el valor `max_time` o `interactive_timeout` , respectivamente.\n",
        "\n",
        "<span id=\"close\" />\n",
        "\n",
        "<span id=\"close-a-batch\" />\n",
        "\n",
        "## Cerrar un lote\n",
        "\n",
        "Un lote se cierra automáticamente cuando sale del gestor de contexto. Cuando se sale del gestor contextual de lotes, el lote pasa al estado \"En curso, no acepta nuevos trabajos\". Esto significa que el lote termina de procesar todos los trabajos en ejecución o en cola hasta que se alcanza el valor TTL máximo. Una vez finalizados todos los trabajos, el lote se cierra inmediatamente. No se pueden enviar trabajos a un lote cerrado.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "05868749-5c03-4540-b780-3e151054e4cf",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\">\n",
        "  El siguiente código requiere que introduzcas tu propia información, como los PUB del estimador y del muestreador, así como un backend.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "39fa154b-d5f2-411f-8953-367bd5e3c879",
      "metadata": {},
      "outputs": [],
      "source": [
        "with Batch(backend=backend) as batch:\n",
        "    estimator = Estimator()\n",
        "    sampler = Sampler()\n",
        "    job1 = estimator.run([estimator_pub])\n",
        "    job2 = sampler.run([sampler_pub])\n",
        "\n",
        "# The batch 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": "92515062-ec5e-41a1-8969-59e78c448b1f",
      "metadata": {},
      "source": [
        "<Admonition type=\"tip\">\n",
        "  Si no utiliza un gestor contextual, cierre manualmente el lote.  Si deja el lote abierto y le envía más trabajos más tarde, es posible que se alcance el TTL máximo antes de que empiecen a ejecutarse los trabajos posteriores, lo que provocará que se cancelen. Puede cerrar un lote en cuanto haya terminado de enviarle trabajos. Cuando un lote se cierra con `batch.close()`, ya no acepta nuevos trabajos, pero los trabajos ya enviados seguirán ejecutándose hasta su finalización y se podrán recuperar sus resultados.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "d1cb86c0-b397-47a9-ad93-055aa71ca327",
      "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",
            "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=133>), shape=(3, 2)), metadata={'circuit_metadata': {}})], metadata={'execution': {'execution_spans': ExecutionSpans([DoubleSliceSpan(<start='2026-02-15 07:58:55', stop='2026-02-15 07:59:02', size=24576>)])}, 'version': 2})\n"
          ]
        }
      ],
      "source": [
        "batch = Batch(backend=backend)\n",
        "\n",
        "# If using qiskit-ibm-runtime earlier than 0.24.0, change `mode=` to `batch=`\n",
        "estimator = Estimator(mode=batch)\n",
        "sampler = Sampler(mode=batch)\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 batch. Running and queued jobs will run to completion.\n",
        "batch.close()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9594105f-b003-43ee-9a5f-5cf3d6410887",
      "metadata": {},
      "source": [
        "<span id=\"batch-details\" />\n",
        "\n",
        "<span id=\"determine-batch-details\" />\n",
        "\n",
        "## Determinar los detalles del lote\n",
        "\n",
        "Para obtener una visión general de la configuración y el estado de un lote, incluidos su TTL interactivo y máximo, utilice la página `batch.details() method`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "8a21ca0e-0373-456c-879f-9bcddda5289a",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "{'id': '970fe01d-d2cf-45f0-b32b-f886b987a462', 'backend_name': 'ibm_torino', 'interactive_timeout': 1, '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': 'batch', 'usage_time': None}\n"
          ]
        }
      ],
      "source": [
        "from qiskit_ibm_runtime import (\n",
        "    QiskitRuntimeService,\n",
        "    batch,\n",
        "    SamplerV2 as Sampler,\n",
        ")\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "\n",
        "with Batch(backend=backend) as batch:\n",
        "    print(batch.details())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cbdc7521-7b4c-4e02-a24d-2b5ca0a11abe",
      "metadata": {},
      "source": [
        "<span id=\"partition\" />\n",
        "\n",
        "<span id=\"reconfigure-jobs-for-parallel-processing\" />\n",
        "\n",
        "## Reconfigurar trabajos para el procesamiento paralelo\n",
        "\n",
        "Existen múltiples formas de reconfigurar los trabajos para aprovechar el procesamiento paralelo que proporciona la dosificación. El siguiente ejemplo muestra cómo puede dividir una larga lista de circuitos en varios trabajos y ejecutarlos como un lote para aprovechar el procesamiento en paralelo.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "31ae3a23-e8bd-4dcd-86c1-10f6d7b5cee4",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime import SamplerV2 as Sampler, Batch\n",
        "from qiskit.circuit.random import random_circuit\n",
        "\n",
        "max_circuits = 100\n",
        "circuits = [pm.run(random_circuit(5, 5)) for _ in range(5 * max_circuits)]\n",
        "for circuit in circuits:\n",
        "    circuit.measure_active()\n",
        "all_partitioned_circuits = []\n",
        "for i in range(0, len(circuits), max_circuits):\n",
        "    all_partitioned_circuits.append(circuits[i : i + max_circuits])\n",
        "jobs = []\n",
        "start_idx = 0\n",
        "\n",
        "with Batch(backend=backend):\n",
        "    sampler = Sampler()\n",
        "    for partitioned_circuits in all_partitioned_circuits:\n",
        "        job = sampler.run(partitioned_circuits)\n",
        "        jobs.append(job)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5d4420f8-9c8d-4953-8561-1b0bdb8372eb",
      "metadata": {},
      "source": [
        "<Admonition type=\"caution\">\n",
        "  Si se establece `backend=backend` en una primitiva, el programa se ejecuta en modo trabajo, incluso si se encuentra dentro de un contexto por lotes o de sesión. La configuración `backend=backend` está obsoleta a partir de Qiskit Runtime v0.24.0.  En su lugar, utilice el `mode` parámetro.\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximos pasos\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendaciones\">\n",
        "  * Prueba un ejemplo en el tutorial «[Combinar opciones de mitigación de errores con la primitiva Estimator](/docs/tutorials/combine-error-mitigation-techniques) ».\n",
        "  * Revise la referencia de [la API de lotes](/docs/api/qiskit-ibm-runtime/batch#batch).\n",
        "  * Ten en cuenta [los límites del trabajo](/docs/guides/job-limits) al enviarlo a una QPU de IBM®.\n",
        "  * Revisar [los modos de ejecución Preguntas frecuentes](/docs/guides/execution-modes-faq).\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
}