{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "0d58aa59",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"QESEM - una función Qiskit de Qedma\"\n",
        "description: \"Ejecute circuitos cuánticos en QPU ruidosas para obtener resultados altamente precisos y sin errores con sobrecargas de tiempo de QPU altamente eficientes, cercanas a los límites fundamentales.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore DESY Multibase, Quasicrystal, Downfolding, Aharonov, Goldack, wavefunctions, Sakuma */}\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dde95705",
      "metadata": {},
      "source": [
        "<span id=\"qesem-a-qiskit-function-by-qedma\" />\n",
        "\n",
        "# QESEM: Una función Qiskit de Qedma\n",
        "\n",
        "*Consulte la [referencia de la API](/docs/api/functions/qedma-qesem)*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6256578e",
      "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 teniendo en cuenta los siguientes requisitos.\n",
        "    Recomendamos utilizar estas versiones o posteriores.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.0\n",
        "    qiskit-ibm-runtime~=0.47.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "13528739",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\" title=\"Nota\">\n",
        "  Las funciones Qiskit son una función experimental disponible únicamente para los usuarios de los planes IBM Quantum® Premium Plan, Flex Plan y On-Prem (a través de IBM Quantum Platform API). Se trata de versiones preliminares sujetas a cambios.\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"overview\" />\n",
        "\n",
        "## Visión general\n",
        "\n",
        "Aunque las unidades de procesamiento cuántico han mejorado considerablemente en los últimos años, los errores debidos al ruido y las imperfecciones del hardware existente siguen siendo un reto fundamental para los desarrolladores de algoritmos cuánticos. A medida que el campo se acerca a los cálculos cuánticos a escala industrial que no pueden verificarse de forma clásica, las soluciones para cancelar el ruido con una precisión garantizada cobran cada vez más importancia. Para superar este reto, Qedma ha desarrollado Quantum Error Mitigation (QESEM), perfectamente integrado en IBM Quantum Platform como una [función Qiskit](/docs/guides/functions).\n",
        "\n",
        "Con QESEM, los usuarios pueden ejecutar sus circuitos cuánticos en QPU con ruido para obtener resultados de gran precisión y sin errores, con una sobrecarga de tiempo de la QPU muy eficiente, cercana a los límites fundamentales. Para lograrlo, QESEM utiliza un conjunto de métodos propios desarrollados por Qedma, destinados a la caracterización y la reducción de errores. Entre las técnicas de reducción de errores se incluyen la optimización de puertas lógicas, la transpilación sensible al ruido, la supresión de errores (ES) y la mitigación de errores no sesgada (EM). Gracias a esta combinación de métodos basados en la caracterización, los usuarios pueden obtener resultados fiables y sin errores para circuitos cuánticos genéricos de gran volumen, lo que abre las puertas a aplicaciones que de otro modo no serían posibles.\n",
        "\n",
        "Para obtener una descripción completa de los componentes subyacentes, así como una demostración a escala industrial, consulte el artículo «[Mitigación fiable y de alta precisión de errores para circuitos cuánticos a escala industrial](https://arxiv.org/abs/2508.10997) ».\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5f761442",
      "metadata": {},
      "source": [
        "<span id=\"description\" />\n",
        "\n",
        "## Descripción\n",
        "\n",
        "Puede utilizar la función QESEM de Qedma para estimar y ejecutar fácilmente sus circuitos con supresión y mitigación de errores, consiguiendo mayores volúmenes de circuitos y mayores precisiones. Para utilizar QESEM, se proporciona un circuito cuántico, un conjunto de observables a medir, un objetivo de precisión estadística para cada observable y una QPU elegida. Antes de ejecutar el circuito con la precisión deseada, puede estimar el tiempo de QPU necesario basándose en un cálculo analítico que no requiere la ejecución del circuito. Una vez que estés satisfecho con la estimación de tiempo QPU, puedes ejecutar el circuito con QESEM.\n",
        "\n",
        "Cuando ejecuta un circuito, QESEM ejecuta un protocolo de caracterización de dispositivos adaptado a su circuito, lo que proporciona un modelo de ruido fiable para los errores que se producen en el circuito. Basándose en la caracterización, QESEM implementa primero una transpilación sensible al ruido para mapear el circuito de entrada en un conjunto de qubits y puertas físicas, lo que minimiza el ruido que afecta al observable objetivo. Entre ellas se incluyen las puertas disponibles de forma nativa (CX/CZ en dispositivos de e IBM® ), así como puertas adicionales optimizadas por QESEM, que conforman el conjunto ampliado de puertas de QESEM. A continuación, QESEM ejecuta un conjunto de circuitos ES y EM basados en la caracterización en la QPU y recopila los resultados de las mediciones. A continuación, se someten a un procesamiento posterior clásico para proporcionar un valor esperado imparcial y una barra de error para cada observable, en función de la precisión solicitada.\n",
        "\n",
        "![Presentación de Qedma QESEM](https://quantum.cloud.ibm.com/docs/images/guides/qedma-qesem/overview.svg)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "74823696",
      "metadata": {},
      "source": [
        "Se ha demostrado que la QESEM proporciona resultados de gran precisión para una gran variedad de aplicaciones cuánticas y en los mayores volúmenes de circuitos que se pueden conseguir hoy en día. QESEM ofrece las siguientes funciones de cara al usuario, demostradas en la sección de pruebas comparativas que figura a continuación:\n",
        "\n",
        "* **Precisión garantizada:** QESEM genera estimaciones imparciales para los valores esperados de los observables. Su método EM cuenta con garantías teóricas que, junto con la caracterización de vanguardia de Qedma, aseguran que la mitigación converge hacia la salida del circuito sin ruido hasta alcanzar la precisión especificada por el usuario. A diferencia de muchos métodos heurísticos EM, que son propensos a errores sistemáticos o sesgos, la precisión garantizada de QESEM es esencial para asegurar resultados fiables en circuitos cuánticos genéricos y observables.\n",
        "* **Escalabilidad a QPU grandes:** el tiempo de QPU de QESEM depende del volumen de los circuitos, pero por lo demás es independiente del número de qubits. Qedma ha demostrado QESEM en los dispositivos cuánticos más grandes disponibles en la actualidad, incluidos los dispositivos Eagle de 127 qubits y Heron de 133 qubits de IBM Quantum.\n",
        "* **Aplicación agnóstica:** QESEM se ha demostrado en una variedad de aplicaciones, incluyendo la simulación hamiltoniana, VQE, QAOA, y la estimación de la amplitud. Los usuarios pueden introducir cualquier circuito cuántico y observable que deseen medir, y obtener resultados precisos y sin errores. Las únicas limitaciones vienen dictadas por las especificaciones del hardware y el tiempo asignado a la QPU, que determinan los volúmenes de circuito accesibles y las precisiones de salida. En cambio, muchas soluciones de reducción de errores son específicas de cada aplicación o implican heurísticas incontroladas, lo que las hace inaplicables a circuitos y aplicaciones cuánticos genéricos.\n",
        "* **Conjunto de puertas ampliado:** QESEM admite puertas de ángulo fraccionario y proporciona puertas de ángulo fraccionario optimizadas para Qedma ( $Rzz(\\theta)$ ) en dispositivos IBM Quantum Heron y Eagle. Este conjunto de puertas ampliado permite una compilación más eficiente y desbloquea volúmenes de circuitos hasta dos veces mayores en comparación con la compilación CX/CZ predeterminada.\n",
        "* **Observables multibase:** QESEM admite observables de entrada compuestos por muchas cadenas de Pauli no conmutativas, como los hamiltonianos genéricos. La elección de las bases de medición y la optimización de la asignación de recursos QPU (disparos y circuitos) se realiza entonces automáticamente por QESEM para minimizar el tiempo QPU requerido para la precisión solicitada. Esta optimización, que tiene en cuenta las fidelidades del hardware y las tasas de ejecución, permite ejecutar circuitos más profundos y obtener mayores precisiones.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "57b41ab0",
      "metadata": {},
      "source": [
        "<span id=\"benchmarks\" />\n",
        "\n",
        "## Referencias comparativas\n",
        "\n",
        "QESEM se ha probado en una amplia variedad de casos de uso y aplicaciones. Los siguientes ejemplos pueden ayudarle a evaluar qué tipos de cargas de trabajo puede ejecutar con QESEM.\n",
        "\n",
        "Un factor de mérito clave para cuantificar la dureza tanto de la mitigación de errores como de la simulación clásica para un circuito y un observable dados es el **volumen activo** : el número de puertas CNOT que afectan al observable en el circuito. El volumen activo depende de la profundidad y anchura del circuito, del peso del observable y de la estructura del circuito, que determina el cono de luz del observable. Para más detalles, consulte la charla de la [Cumbre Cuántica de 2024 IBM](https://www.youtube.com/watch?v=Hd-IGvuARfE\\&t=1730s). QESEM proporciona un valor particularmente grande en el régimen de alto volumen, dando resultados fiables para circuitos y observables genéricos.\n",
        "\n",
        "![Volumen activo](https://quantum.cloud.ibm.com/docs/images/guides/qedma-qesem/active_volume.svg)\n",
        "\n",
        "| Aplicación                           | Número de qubits | Dispositivo   | Descripción del circuito                                 | Precisión | Tiempo total | Uso del tiempo de ejecución |\n",
        "| ------------------------------------ | ---------------- | ------------- | -------------------------------------------------------- | --------- | ------------ | --------------------------- |\n",
        "| Circuito VQE                         | 8                | Águila ( r3 ) | 21 capas totales, 9 bases de medición, 1D chain          | 98 %      | 35 min       | 14 minutos                  |\n",
        "| Kicked Ising                         | 28               | Águila ( r3 ) | 3 capas únicas x 3 pasos, 2D topología heavy-hex         | 97 %      | 22 minutos   | 4 minutos                   |\n",
        "| Kicked Ising                         | 28               | Águila ( r3 ) | 3 capas únicas x 8 pasos, 2D topología heavy-hex         | 97 %      | 116 min      | 23 minutos                  |\n",
        "| Simulación hamiltoniana trotterizada | 40               | Águila ( r3 ) | 2 capas únicas x 10 pasos Trotter, 1D cadena             | 97 %      | 3 horas      | 25 min                      |\n",
        "| Simulación hamiltoniana trotterizada | 119              | Águila ( r3 ) | 3 capas únicas x 9 pasos Trotter, 2D topología heavy-hex | 95%       | 6.5 horas    | 45 min                      |\n",
        "| Kicked Ising                         | 136              | Garza ( r2 )  | 3 capas únicas x 15 pasos, 2D topología heavy-hex        | 99%       | 52 min       | 9 min                       |\n",
        "\n",
        "La precisión se mide aquí en relación con el valor ideal del observable: $\\frac{\\langle O \\rangle_{ideal} - \\epsilon}{\\langle O \\rangle_{ideal}}$, donde ' $\\epsilon$ ' es la precisión absoluta de la atenuación (fijada por la entrada del usuario), y $\\langle O \\rangle_{ideal}$ es el observable en el circuito sin ruido.\n",
        "el \"uso en tiempo de ejecución\" mide el uso del benchmark en modo batch (suma sobre el uso de trabajos individuales), mientras que el \"tiempo total\" mide el uso en modo sesión (tiempo de muro del experimento), que incluye tiempos clásicos y de comunicación adicionales. QESEM está disponible para su ejecución en ambos modos, de modo que los usuarios puedan aprovechar al máximo sus recursos disponibles.\n",
        "\n",
        "Los circuitos Kicked Ising de 28 qubits simulan el Cuasicristal de Tiempo Discreto estudiado por Shinjo et al. (véase [arXiv 2403.16718](https://arxiv.org/abs/2403.16718) y [Q2B24 Tokio](https://www.youtube.com/watch?v=tQW6FdLc6zo) ) en tres bucles conectados de ibm\\_kawasaki. Los parámetros del circuito tomados aquí son $(\\theta_x, \\theta_z) = (0.9 \\pi, 0)$, con un estado inicial ferromagnético $| \\psi_0 \\rangle = | 0 \\rangle ^{\\otimes n}$. El observable medido es el valor absoluto de la magnetización $M = |\\frac{1}{28} \\sum_{i=0}^{27} \\langle Z_i \\rangle|$. El experimento Kicked Ising a escala comercial se ejecutó en los 136 mejores qubits de ibm\\_fez; este punto de referencia concreto se ejecutó en el ángulo Clifford $(\\theta_x, \\theta_z) = (\\pi, 0)$, en el que el volumen activo crece lentamente con la profundidad del circuito, lo que -junto con las altas fidelidades del dispositivo- permite una alta precisión en un tiempo de ejecución corto.\n",
        "\n",
        "Los circuitos de simulación hamiltonianos trotterizados son para un modelo Ising de campo transversal en ángulos fraccionarios: $(\\theta_{zz}, \\theta_x) = (\\pi / 4, \\pi /8)$ y $(\\theta_{zz}, \\theta_x) = (\\pi / 6, \\pi / 8)$ correspondientemente (véase [Q2B24 Tokio](https://www.youtube.com/watch?v=tQW6FdLc6zo) ). El circuito a escala comercial se ejecutó con los 119 mejores qubits de ibm\\_brisbane, mientras que el experimento de 40 qubits se ejecutó con la mejor cadena disponible. La precisión se indica para la magnetización; también se obtuvieron resultados de alta precisión para observables de mayor peso.\n",
        "\n",
        "El circuito VQE se desarrolló junto con investigadores del Centro de Tecnología y Aplicaciones Cuánticas del Deutsches Elektronen-Synchrotron (DESY). En este caso, el observable objetivo era un hamiltoniano formado por un gran número de cadenas de Pauli no conmutativas, lo que pone de relieve el rendimiento optimizado de QESEM para observables multibase. La mitigación se aplicó a un ansatz optimizado de forma clásica; aunque estos resultados aún no se han publicado, se obtendrán resultados de la misma calidad para distintos circuitos con propiedades estructurales similares.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d6fb65de",
      "metadata": {},
      "source": [
        "<span id=\"get-started\" />\n",
        "\n",
        "## Cómo empezar\n",
        "\n",
        "Autentíquese utilizando su [clave API IBM Quantum Platform](http://quantum.cloud.ibm.com/) y seleccione la función QESEM Qiskit de la siguiente manera. (En este fragmento de código se da por hecho que ya has [guardado tu cuenta](/docs/guides/functions-get-started#install-qiskit-functions-catalog-client) en tu entorno local.)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "95a715d2",
      "metadata": {},
      "outputs": [],
      "source": [
        "import qiskit\n",
        "from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
        "\n",
        "catalog = QiskitFunctionsCatalog(channel=\"ibm_quantum_platform\")\n",
        "\n",
        "# verify that you have access to the function\n",
        "catalog.list()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "2d78b033",
      "metadata": {},
      "outputs": [],
      "source": [
        "# load the function\n",
        "qesem_function = catalog.load(\"qedma/qesem\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5f0120d8",
      "metadata": {},
      "source": [
        "<span id=\"examples\" />\n",
        "\n",
        "## Ejemplos\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7d102971",
      "metadata": {},
      "source": [
        "<span id=\"time-estimation-job-example\" />\n",
        "\n",
        "### Ejemplo de trabajo de estimación de tiempos\n",
        "\n",
        "`backend_name`La tarea de estimación de tiempo resulta útil para calcular el tiempo de QPU necesario para un y un determinados `pub` . `backend_name` También se puede configurar con cualquier backend de simulador; por ejemplo, `fake_fez`.\n",
        "\n",
        "QESEM utiliza un método EM cuasiprobabilístico basado en la caracterización. Este método conlleva una sobrecarga de tiempo de la QPU que varía aproximadamente de la siguiente manera:\n",
        "\n",
        "$T_{QPU} = a \\frac{e^{\\alpha IF\\cdot V_a}}{\\epsilon^2} + b$\n",
        "\n",
        "Donde $V_a$ es el volumen activo del circuito, $\\epsilon$ es la precisión deseada y $IF$ es la infidelidad de las puertas nativas.\n",
        "\n",
        "Ten en cuenta que `\"estimate_time_only\": \"empirical\"` utiliza unos minutos de tiempo de QPU para calcular el tiempo necesario para el trabajo (si el backend es un dispositivo real; si se trata de un simulador, no se utiliza tiempo de QPU). Esto suele tardar unos 5 minutos, pero no más de 10 minutos. Si la infidelidad varía drásticamente entre la tarea de estimación empírica del tiempo y la tarea de mitigación, el tiempo de la QPU también variará drásticamente.\n",
        "\n",
        "Para empezar, pruebe este ejemplo básico de estimación del tiempo de QPU necesario para ejecutar QESEM para un determinado `pub`:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "d56e1440",
      "metadata": {},
      "outputs": [],
      "source": [
        "backend_name = \"fake_fez\"\n",
        "\n",
        "circ = qiskit.QuantumCircuit(5)\n",
        "circ.cx(0, 1)\n",
        "circ.cx(2, 3)\n",
        "circ.cx(1, 2)\n",
        "circ.cx(3, 4)\n",
        "\n",
        "avg_magnetization = qiskit.quantum_info.SparsePauliOp.from_sparse_list(\n",
        "    [(\"Z\", [q], 1 / 5) for q in range(5)], num_qubits=5\n",
        ")\n",
        "other_observable = qiskit.quantum_info.SparsePauliOp.from_sparse_list(\n",
        "    [(\"ZZ\", [0, 1], 1.0), (\"XZ\", [1, 4], 0.5)], num_qubits=5\n",
        ")\n",
        "\n",
        "time_estimation_job = qesem_function.run(\n",
        "    pubs=[(circ, [avg_magnetization, other_observable])],\n",
        "    options={\n",
        "        \"estimate_time_only\": \"empirical\",\n",
        "    },\n",
        "    backend_name=backend_name,  # example: \"fake_fez\", \"ibm_fez\"\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "a6eb4bda04796ac5",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2026-05-03T12:04:42.901739Z",
          "start_time": "2026-05-03T12:02:20.288020Z"
        }
      },
      "outputs": [],
      "source": [
        "time_estimate_result = (\n",
        "    time_estimation_job.result()\n",
        ")  # a list of results per pub (circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5ec8053b",
      "metadata": {},
      "source": [
        "El siguiente fragmento de código describe cómo obtener diferentes métricas de ejecución del trabajo de estimación de tiempo (`estimate_time_only` está configurado):\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 106,
      "id": "77a9dca8efb1a37b",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2026-05-12T11:22:06.848571Z",
          "start_time": "2026-05-12T11:22:06.838844Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The estimated QPU time for mitigation for this PUB is: 300\n",
            "The QPU time that this time estimation job took is (here it is 0 because we used fake_fez): 0\n",
            "Gates fidelity measured during the experiment: {'CZ': 0.9951354916722668, 'ID1Q': 0.9991246627329172}\n",
            "Total shots: 220000\n",
            "Resource usage breakdown: {'RUNNING: MAPPING': {'CPU_TIME': 33.6066133165732, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: OPTIMIZING_FOR_HARDWARE': {'CPU_TIME': 184.53575124032795, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: WAITING_FOR_QPU': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: EXECUTING_QPU': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: POST_PROCESSING': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}}\n"
          ]
        }
      ],
      "source": [
        "pub_result = time_estimate_result[0]\n",
        "\n",
        "print(\n",
        "    f\"The estimated QPU time for mitigation for this PUB is: {pub_result.metadata['time_estimation_sec']}\"\n",
        ")\n",
        "print(\n",
        "    f\"The QPU time that this time estimation job took is (here it is 0 because we used fake_fez): {pub_result.metadata['total_qpu_time']}\"\n",
        ")\n",
        "print(\n",
        "    f\"Gates fidelity measured during the experiment: {pub_result.metadata['gate_fidelities']}\"\n",
        ")\n",
        "print(f\"Total shots: {pub_result.metadata['total_shots']}\")\n",
        "print(f\"Resource usage breakdown: {pub_result.metadata['resource_usage']}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5f68f983189f00a1",
      "metadata": {},
      "source": [
        "Cuando se activa la estimación empírica del tiempo, QESEM ejecuta un pequeño número de circuitos para proporcionar una estimación más precisa del tiempo de la QPU. Los resultados de mitigación de estos circuitos están disponibles en el `empirical_estimation_mitigation_results` campo del trabajo.\n",
        "\n",
        "Dado que estos resultados se han obtenido a partir de una muestra limitada de circuitos, su precisión es considerablemente menor que la de los resultados finales obtenidos tras completar el proceso de mitigación con QESEM. Sin embargo, cuando el circuito es pequeño o la precisión deseada es baja, las medidas de mitigación aplicadas durante la estimación empírica del tiempo pueden ser suficientes para alcanzar la precisión deseada, por lo que quizá no sea necesario llevar a cabo el proceso completo de mitigación.\n",
        "\n",
        "El `empirical_estimation_mitigation_results` campo es una lista de `PrimitiveResult` objetos por cada parámetro de entrada. Si el circuito no está parametrizado, la lista tendrá una longitud de 1.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "7acca648911dacd5",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2026-05-05T13:41:38.131003Z",
          "start_time": "2026-05-05T13:41:38.127666Z"
        }
      },
      "outputs": [],
      "source": [
        "empirical_estimation_mitigation_results = time_estimate_result[0].metadata[\n",
        "    \"empirical_estimation_mitigation_results\"\n",
        "][0]  # a list per parameter"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "60b482803339ce27",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2026-05-05T15:23:58.817671Z",
          "start_time": "2026-05-05T15:23:58.811680Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Partial results for the observables:\n",
            "    Mitigated expectation values: [1.00347302 1.00693905]\n",
            "    Mitigated error bars: [0.00304061 0.00714276]\n",
            "    Number of shots used for mitigation: 180000\n",
            "    Qubit mapping: [[[0, 136], [1, 143], [2, 142], [3, 141], [4, 140]]]\n",
            "    Number of measurement bases: 2\n",
            "\n",
            "Results for each observable:\n",
            "Observable 1: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())\n",
            "    QESEM mitigated value: 1.003473015776871 ± 0.0030406128032204015\n",
            "Observable 2: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())\n",
            "    QESEM mitigated value: 1.0069390542613554 ± 0.0071427606736885925\n"
          ]
        }
      ],
      "source": [
        "print(\"Partial results for the observables:\")\n",
        "\n",
        "print(\n",
        "    f\"    Mitigated expectation values: {empirical_estimation_mitigation_results.data.evs}\"\n",
        ")\n",
        "print(\n",
        "    f\"    Mitigated error bars: {empirical_estimation_mitigation_results.data.stds}\"\n",
        ")\n",
        "print(\n",
        "    f\"    Number of shots used for mitigation: {empirical_estimation_mitigation_results.metadata['mitigation_shots']}\"\n",
        ")\n",
        "transpiled_circ = empirical_estimation_mitigation_results.metadata[\n",
        "    \"transpiled_circ\"\n",
        "]\n",
        "print(f\"    Qubit mapping: {transpiled_circ['qubit_maps']}\")\n",
        "print(\n",
        "    f\"    Number of measurement bases: {transpiled_circ['num_measurement_bases']}\\n\"\n",
        ")\n",
        "\n",
        "# results per obs\n",
        "emp_obs_results = empirical_estimation_mitigation_results.metadata[\"results\"][\n",
        "    0\n",
        "]\n",
        "# print(f\"Results for each observable: {results}\")\n",
        "print(\"Results for each observable:\")\n",
        "\n",
        "for i, (obs_array, result_dict) in enumerate(emp_obs_results):\n",
        "    # obs_array, result_dict = results\n",
        "    print(f\"Observable {i+1}: {obs_array}\")\n",
        "    print(\n",
        "        f\"    QESEM mitigated value: {result_dict['qesem']['value']} \\u00b1 {result_dict['qesem']['error_bar']}\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ae10a4c8",
      "metadata": {},
      "source": [
        "<span id=\"qesem-mitigation-job-example\" />\n",
        "\n",
        "### Ejemplo de tarea de mitigación en QESEM\n",
        "\n",
        "El siguiente ejemplo ejecuta un trabajo QESEM:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "e7351d6b",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2026-05-05T13:42:11.391952Z",
          "start_time": "2026-05-05T13:42:01.266109Z"
        }
      },
      "outputs": [],
      "source": [
        "sample_job = qesem_function.run(\n",
        "    pubs=[(circ, [avg_magnetization, other_observable])],\n",
        "    backend_name=backend_name,  # example: \"ibm_fez\"\n",
        "    # options = {\n",
        "    #     \"estimate_time_only\": \"empirical\",\n",
        "    #     \"default_precision\": 0.2,  # Default precision is applied to all pubs that don't have a precision specified, see API reference for more details\n",
        "    #     \"max_execution_time\": 3600,  # You can specify a maximum QPU time in seconds, see API reference for more details\n",
        "    #     \"transpilation_level\": \"standard\",  # \"minimal_with_layout_opt\" for minimal transpilation, see API reference for more details\n",
        "    #     \"parallel_execution\": True,  # True for parallel execution, see API reference for more details\n",
        "    # },\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f7f7fe68",
      "metadata": {},
      "source": [
        "Para obtener una descripción detallada de cada campo de entrada y cada opción, consulta la [referencia de la API de QESEM](/docs/api/functions/qedma-qesem).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dfe99043",
      "metadata": {},
      "source": [
        "Puede utilizar las conocidas API sin servidor de Qiskit para comprobar el estado de su carga de trabajo Qiskit Function o devolver resultados:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 25,
      "id": "856fe992",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "3ac6b2df-15b0-4dc0-8f48-cf14bd20a1c8\n",
            "DONE\n"
          ]
        }
      ],
      "source": [
        "# Print the ID so you can use it later, if necessary\n",
        "print(sample_job.job_id)\n",
        "print(sample_job.status())\n",
        "sample_result = sample_job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a9e51542",
      "metadata": {},
      "source": [
        "El siguiente fragmento de código muestra cómo recuperar los resultados de la mitigación y las métricas de ejecución. Estos contienen datos esenciales que permiten comprender mejor cómo influyen los distintos parámetros en la ejecución del QESEM. También puede resultar útil a la hora de redactar un trabajo basado en tu investigación.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 50,
      "id": "117c2e4aa624ed51",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2026-05-12T11:23:45.739919Z",
          "start_time": "2026-05-12T11:23:45.737884Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "PUB 0:\n",
            "  The QPU time that this job took is (here it is 0 because we used fake_fez): 0.0\n",
            "  Gates fidelity measured during the experiment: {'CZ': 0.9953704216147041, 'ID1Q': 0.9991834123567518}\n",
            "  Total shots: 446000\n",
            "  Number of shots used for mitigation: 194000\n",
            "  Resource usage breakdown: {'RUNNING: MAPPING': {'CPU_TIME': 32.52745003718883, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: OPTIMIZING_FOR_HARDWARE': {'CPU_TIME': 257.850521848537, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: WAITING_FOR_QPU': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: EXECUTING_QPU': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: POST_PROCESSING': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}}\n"
          ]
        }
      ],
      "source": [
        "for pub_idx, pub_result in enumerate(\n",
        "    sample_result\n",
        "):  # each element in the list is a result for a different pub, here we sent only one pub\n",
        "    print(f\"\\nPUB {pub_idx}:\")\n",
        "    print(\n",
        "        f\"  The QPU time that this job took is (here it is 0 because we used fake_fez): {pub_result.metadata['total_qpu_time']}\"\n",
        "    )\n",
        "    print(\n",
        "        f\"  Gates fidelity measured during the experiment: {pub_result.metadata['gate_fidelities']}\"\n",
        "    )\n",
        "    print(f\"  Total shots: {pub_result.metadata['total_shots']}\")\n",
        "    print(\n",
        "        f\"  Number of shots used for mitigation: {pub_result.metadata['mitigation_shots']}\"\n",
        "    )\n",
        "    print(\n",
        "        f\"  Resource usage breakdown: {pub_result.metadata['resource_usage']}\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3f71cc3a",
      "metadata": {},
      "source": [
        "En `metadata[\"results\"]`, los resultados se agrupan primero por instancia de circuito y, a continuación, por observable.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 99,
      "id": "a5899795",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Full QESEM mitigation results:\n",
            "\n",
            "PUB 0:\n",
            "  Mitigated expectation values: [1.00648343 1.00636289]\n",
            "  Mitigated error bars: [0.00253812 0.00693586]\n",
            "  Unmitigated expectation values: [0.98031429 0.96357143]\n",
            "  Unmitigated error bars: [0.00124128 0.00578812]\n",
            "  Transpiled circuits:\n",
            "    Circuit 0:\n",
            "      Qubit mapping: [[[0, 140], [1, 141], [2, 142], [3, 143], [4, 136]]]\n",
            "      Measurement bases: 2\n",
            "  Results for each observable:\n",
            "    Circuit 0:\n",
            "      Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())\n",
            "        QESEM mitigated value: 1.0064834305181962 ± 0.002538119914534849\n",
            "        Unmitigated value: 0.9803142857142859 ± 0.0012412835813609938\n",
            "      Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())\n",
            "        QESEM mitigated value: 1.0063628870614818 ± 0.006935859820870656\n",
            "        Unmitigated value: 0.9635714285714285 ± 0.005788121870526659\n"
          ]
        }
      ],
      "source": [
        "print(\"Full QESEM mitigation results:\")\n",
        "\n",
        "for pub_idx, pub_result in enumerate(sample_result):\n",
        "    print(f\"\\nPUB {pub_idx}:\")\n",
        "\n",
        "    print(f\"  Mitigated expectation values: {pub_result.data.evs}\")\n",
        "    print(f\"  Mitigated error bars: {pub_result.data.stds}\")\n",
        "    noisy_results = pub_result.metadata.get(\"noisy_results\")\n",
        "    print(f\"  Unmitigated expectation values: {noisy_results.evs}\")\n",
        "    print(f\"  Unmitigated error bars: {noisy_results.stds}\")\n",
        "\n",
        "    print(\"  Transpiled circuits:\")\n",
        "    for circ_idx, transpiled_circ in enumerate(\n",
        "        pub_result.metadata[\"transpiled_circs\"]\n",
        "    ):\n",
        "        print(f\"    Circuit {circ_idx}:\")\n",
        "        # print(f\"      Circuit: \\n {transpiled_circ['circuit']}\") # not printing it because it's long but you can see the transpiled circuit itself\n",
        "        print(f\"      Qubit mapping: {transpiled_circ['qubit_maps']}\")\n",
        "        print(\n",
        "            f\"      Measurement bases: {transpiled_circ['num_measurement_bases']}\"\n",
        "        )\n",
        "\n",
        "    print(\"  Results for each observable:\")\n",
        "    for circ_idx, circ_results in enumerate(pub_result.metadata[\"results\"]):\n",
        "        print(f\"    Circuit {circ_idx}:\")\n",
        "        for obs_idx, (obs_array, result_dict) in enumerate(circ_results):\n",
        "            print(f\"      Observable {obs_idx}: {obs_array}\")\n",
        "            print(\n",
        "                f\"        QESEM mitigated value: {result_dict['qesem']['value']} ± {result_dict['qesem']['error_bar']}\"\n",
        "            )\n",
        "            print(\n",
        "                f\"        Unmitigated value: {result_dict['unmitigated']['value']} ± {result_dict['unmitigated']['error_bar']}\"\n",
        "            )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "345524a3",
      "metadata": {},
      "source": [
        "**Desglose de los principales resultados:**\n",
        "\n",
        "* `mitigated`: el valor esperado de QESEM totalmente mitigado.\n",
        "* `unmitigated`: el resultado bruto del ruido físico sin mitigación de errores.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "65a2e503",
      "metadata": {},
      "source": [
        "<span id=\"qesem-heuristic-extrapolation-results\" />\n",
        "\n",
        "#### Resultados de la extrapolación heurística de QESEM\n",
        "\n",
        "En una ejecución estándar de QESEM con un único `precision` flotante, los resultados también incluyen puntos de escalado de ruido disponibles automáticamente que se utilizan para la heurística de QESEM. Estos puntos se calculan sin recursos adicionales de la QPU.\n",
        "\n",
        "La escala `1.0` representa el nivel de ruido del dispositivo físico con mitigación de lectura (REM), mientras que la escala `2.0` corresponde al punto complementario con amplificación de ruido, también con REM. Estos puntos se utilizan para obtener el `qesem_heuristic` resultado.\n",
        "\n",
        "* `qesem_heuristic`: una estimación de tipo ZNE calculada a partir de los datos disponibles, ajustados en función del ruido. Actualmente, se utiliza una extrapolación exponencial.\n",
        "* `noise_scaling.results_with_REM`: valores esperados en diferentes escalas de ruido, todos con mitigación de la lectura (REM).\n",
        "\n",
        "Un detalle sutil pero importante es que el resultado de la escala `1.0` no es el mismo que el `unmitigated` resultado. Ambos se refieren al nivel de ruido del dispositivo físico, pero el punto de la escala `1.0` incluye la mitigación de la lectura, mientras que `unmitigated` no.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 101,
      "id": "21afd3d2",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QESEM heuristic results:\n",
            "\n",
            "PUB 0:\n",
            "  Circuit 0:\n",
            "    Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())\n",
            "      QESEM heuristic:\n",
            "        Value: 1.0008161638888535 ± 0.0038859458884403964\n",
            "        Extrapolation: exponential\n",
            "        Scale factors: [1.0, 2.0]\n",
            "      Noise scaling results:\n",
            "        Scaling method: QESEM\n",
            "        Results with Readout mitigation (REM):\n",
            "          Scale factor 1.0: 0.9918395459270772 ± 0.0012565417579355634\n",
            "          Scale factor 2.0: 0.982943441922748 ± 0.0028919278067695018\n",
            "    Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())\n",
            "      QESEM heuristic:\n",
            "        Value: 0.9960853148925298 ± 0.013811635038961175\n",
            "        Extrapolation: exponential\n",
            "        Scale factors: [1.0, 2.0]\n",
            "      Noise scaling results:\n",
            "        Scaling method: QESEM\n",
            "        Results with Readout mitigation (REM):\n",
            "          Scale factor 1.0: 0.9902860583785115 ± 0.005921236914723409\n",
            "          Scale factor 2.0: 0.984520565414274 ± 0.006909522262347639\n"
          ]
        }
      ],
      "source": [
        "print(\"QESEM heuristic results:\")\n",
        "\n",
        "for pub_idx, pub_result in enumerate(sample_result):\n",
        "    print(f\"\\nPUB {pub_idx}:\")\n",
        "    for circ_idx, circ_results in enumerate(pub_result.metadata[\"results\"]):\n",
        "        print(f\"  Circuit {circ_idx}:\")\n",
        "        for obs_idx, (obs_array, result_dict) in enumerate(circ_results):\n",
        "            print(f\"    Observable {obs_idx}: {obs_array}\")\n",
        "            qesem_heuristic = result_dict[\"qesem_heuristic\"][0]\n",
        "            print(\"      QESEM heuristic:\")\n",
        "            print(\n",
        "                f\"        Value: {qesem_heuristic['value']} ± {qesem_heuristic['error_bar']}\"\n",
        "            )\n",
        "            print(\n",
        "                f\"        Extrapolation: {qesem_heuristic['extrapolation']}\"\n",
        "            )\n",
        "            print(\n",
        "                f\"        Scale factors: {qesem_heuristic['scale_factors']}\"\n",
        "            )\n",
        "            noise_scaling = result_dict[\"noise_scaling\"]\n",
        "            print(\"      Noise scaling results:\")\n",
        "            print(\n",
        "                f\"        Scaling method: {noise_scaling['scaling_method']}\"\n",
        "            )\n",
        "            print(\"        Results with Readout mitigation (REM):\")\n",
        "            for rem_result in sorted(\n",
        "                (\n",
        "                    item\n",
        "                    for item in noise_scaling[\"results_with_REM\"]\n",
        "                    if item[\"scale\"] != 0.0\n",
        "                ),\n",
        "                key=lambda item: item[\"scale\"],\n",
        "            ):\n",
        "                print(\n",
        "                    f\"          Scale factor {rem_result['scale']}: {rem_result['value']} ± {rem_result['error_bar']}\"\n",
        "                )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "899d229a",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\">\n",
        "  Los siguientes ejemplos se centran en entradas y resultados específicos de cada función, por lo que no muestran las métricas completas de ejecución en cada ocasión. Los metadatos de nivel superior mostrados anteriormente, como <code>tiempo\\_total\\_qpu</code>, <code>gate\\_fidelities</code>, <code>total\\_tiros</code>, <code>medidas de mitigación</code> y <code>uso\\_de\\_recursos</code>, también están disponibles para estos trabajos.\n",
        "\n",
        "  Algunas variables de los ejemplos anteriores, como el backend, los observables y los parámetros del circuito base, se reutilizan a continuación para mayor concisión.\n",
        "</Admonition>\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Todos los ejemplos siguientes también se pueden ejecutar con una estimación empírica del tiempo. Para activarla, introduce « <code>\"estimate\\_time\\_only\": \"empírico\"</code> » en las opciones de la función.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "079cb5be",
      "metadata": {},
      "source": [
        "<span id=\"parameterized-circuit-example\" />\n",
        "\n",
        "### Ejemplo de circuito parametrizado\n",
        "\n",
        "Muchos algoritmos evalúan el mismo circuito con distintos valores de los parámetros. Al enviar el circuito parametrizado como un único trabajo de QESEM, este puede compartir la caracterización y la calibración entre las distintas instancias del circuito, lo que puede reducir la sobrecarga de tiempo de la QPU en comparación con la ejecución de trabajos independientes.\n",
        "\n",
        "Para enviar un circuito parametrizado es necesario utilizar el `\"minimal_with_layout_opt\"` nivel de transpilación.\n",
        "Los circuitos presentados en este nivel ya deben estar expresados utilizando las puertas básicas del backend, en función del backend en cuestión. En este nivel, QESEM mantiene la estructura enviada lo más cercana posible al circuito de entrada, respeta las barreras durante la estratificación (agrupación de operaciones en capas de puertas paralelas de dos qubits) y, además, gestiona automáticamente la asignación de hardware a qubits de alta fidelidad y la conectividad de los dispositivos.\n",
        "\n",
        "En la práctica, esto significa que debes transpilar los circuitos a las puertas básicas del backend de destino antes de enviarlos. A continuación se muestra un ejemplo sencillo de transpilación de puertas básicas.\n",
        "\n",
        "Actualmente, QESEM solo admite una variable observable por conjunto de parámetros. Las dos filas de parámetros que aparecen a continuación están agrupadas con los dos observables: la primera fila se mide con `avg_magnetization`, y la segunda fila se mide con `other_observable`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "704f8aa5",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Transpile to the backend basis gates only. With minimal_with_layout_opt, QESEM handles hardware mapping/connectivity and observable layout internally.\n",
        "from qiskit_ibm_runtime.fake_provider import FakeFez\n",
        "\n",
        "backend = FakeFez()\n",
        "basis = backend.operation_names\n",
        "print(basis)\n",
        "\n",
        "param0 = qiskit.circuit.Parameter(\"param0\")\n",
        "param1 = qiskit.circuit.Parameter(\"param1\")\n",
        "parametrized_circ = qiskit.QuantumCircuit(5)\n",
        "parametrized_circ.rx(param0, 0)\n",
        "parametrized_circ.rx(param1, 1)\n",
        "parametrized_circ.cx(0, 1)\n",
        "parametrized_circ.cx(2, 3)\n",
        "parametrized_circ.cx(1, 2)\n",
        "parametrized_circ.cx(3, 4)\n",
        "\n",
        "parametrized_circ = qiskit.transpile(\n",
        "    parametrized_circ, basis_gates=basis, optimization_level=1\n",
        ")\n",
        "parametrized_parameter_values = [[0.5, 0.1], [0.0, 0.6]]\n",
        "parametrized_observables = [avg_magnetization, other_observable]\n",
        "\n",
        "parametrized_job = qesem_function.run(\n",
        "    pubs=[\n",
        "        (\n",
        "            parametrized_circ,\n",
        "            parametrized_observables,\n",
        "            parametrized_parameter_values,\n",
        "            0.1,\n",
        "        )\n",
        "    ],\n",
        "    backend_name=backend_name,\n",
        "    options={\n",
        "        \"max_execution_time\": 300,\n",
        "        \"transpilation_level\": \"minimal_with_layout_opt\",\n",
        "    },\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 72,
      "id": "85a452fc",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "d1b0e29b-196c-4896-aec6-44a268ebd874\n",
            "DONE\n"
          ]
        }
      ],
      "source": [
        "print(parametrized_job.job_id)\n",
        "print(parametrized_job.status())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 73,
      "id": "244cd3b2",
      "metadata": {},
      "outputs": [],
      "source": [
        "parametrized_result = parametrized_job.result()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 77,
      "id": "03399db5",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Parameterized circuit QESEM results:\n",
            "\n",
            "PUB 0:\n",
            "  Mitigated expectation values: [0.92392021 0.82517653]\n",
            "  Mitigated error bars: [0.00565281 0.00616016]\n",
            "  Unmitigated expectation values: [0.9028     0.78771429]\n",
            "  Unmitigated error bars: [0.00335142 0.00925413]\n",
            "  Results for each parameter value:\n",
            "    Parameter set 0: [0.5, 0.1]\n",
            "      Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())\n",
            "        QESEM mitigated value: 0.923920210615709 ± 0.005652811570890183\n",
            "        Unmitigated value: 0.9028 ± 0.0033514176105045447\n",
            "    Parameter set 1: [0.0, 0.6]\n",
            "      Observable 0: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())\n",
            "        QESEM mitigated value: 0.8251765289285893 ± 0.006160161743353999\n",
            "        Unmitigated value: 0.7877142857142858 ± 0.009254130564027902\n"
          ]
        }
      ],
      "source": [
        "print(\"Parameterized circuit QESEM results:\")\n",
        "\n",
        "for pub_idx, pub_result in enumerate(parametrized_result):\n",
        "    print(f\"\\nPUB {pub_idx}:\")\n",
        "    print(f\"  Mitigated expectation values: {pub_result.data.evs}\")\n",
        "    print(f\"  Mitigated error bars: {pub_result.data.stds}\")\n",
        "    noisy_results = pub_result.metadata[\"noisy_results\"]\n",
        "    print(f\"  Unmitigated expectation values: {noisy_results.evs}\")\n",
        "    print(f\"  Unmitigated error bars: {noisy_results.stds}\")\n",
        "    print(\"  Results for each parameter value:\")\n",
        "    for param_idx, param_results in enumerate(pub_result.metadata[\"results\"]):\n",
        "        print(\n",
        "            f\"    Parameter set {param_idx}: {parametrized_parameter_values[param_idx]}\"\n",
        "        )\n",
        "        for obs_idx, (obs_array, result_dict) in enumerate(param_results):\n",
        "            print(f\"      Observable {obs_idx}: {obs_array}\")\n",
        "            print(\n",
        "                f\"        QESEM mitigated value: {result_dict['qesem']['value']} ± {result_dict['qesem']['error_bar']}\"\n",
        "            )\n",
        "            print(\n",
        "                f\"        Unmitigated value: {result_dict['unmitigated']['value']} ± {result_dict['unmitigated']['error_bar']}\"\n",
        "            )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d6d1b6c2",
      "metadata": {},
      "source": [
        "<span id=\"multi-pub-example\" />\n",
        "\n",
        "### Ejemplo de «Multi-pub»\n",
        "\n",
        "La ejecución en varios pubs resulta útil cuando se desea ejecutar varios circuitos relacionados en un único trabajo de QESEM. Al igual que la ejecución parametrizada, esto puede reducir la sobrecarga, ya que QESEM puede compartir la caracterización y la calibración entre las distintas instancias del circuito, en lugar de repetirlas en trabajos independientes.\n",
        "\n",
        "Esto resulta especialmente útil para circuitos con una estructura de capas compartidas, como las cargas de trabajo **de tipo Trotter**, en las que diferentes circuitos reutilizan las mismas capas únicas. En ese caso, realizarlos conjuntamente puede reducir el coste de la caracterización en comparación con los trabajos independientes de QESEM.\n",
        "\n",
        "Los trabajos en varios bares requieren `\"transpilation_level\": \"minimal_with_layout_opt\"`. Al igual que en el ejemplo parametrizado, los circuitos deben transpilarse a las puertas básicas del backend de destino antes de su envío. A continuación, QESEM se encarga internamente de la conectividad de los dispositivos, su disposición y su asignación a qubits de alta fidelidad.\n",
        "\n",
        "Cada PUB que aparece a continuación contiene un circuito y los mismos dos observables utilizados anteriormente en el cuaderno, por lo que el resultado devuelto `PrimitiveResult` contiene uno `PubResult` por cada circuito de entrada.\n",
        "\n",
        "En el ejemplo siguiente se utilizan dos circuitos de Trotter sencillos con el mismo patrón de capas: `circ_a` tiene una capa de Trotter, y `circ_b` repite el mismo patrón de capas dos veces. Esto deja clara la estructura compartida.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "8cc663fc",
      "metadata": {},
      "outputs": [],
      "source": [
        "def make_trotter_circuit(num_qubits, num_layers, zz_angle=0.2, x_angle=0.1):\n",
        "    trotter_circ = qiskit.QuantumCircuit(num_qubits)\n",
        "    for _ in range(num_layers):\n",
        "        for q in range(num_qubits):\n",
        "            trotter_circ.rx(x_angle, q)\n",
        "        trotter_circ.barrier()\n",
        "        for q in range(0, num_qubits - 1, 2):\n",
        "            trotter_circ.rzz(zz_angle, q, q + 1)\n",
        "        trotter_circ.barrier()\n",
        "        for q in range(1, num_qubits - 1, 2):\n",
        "            trotter_circ.rzz(zz_angle, q, q + 1)\n",
        "        trotter_circ.barrier()\n",
        "    return trotter_circ\n",
        "\n",
        "\n",
        "circ_a = make_trotter_circuit(num_qubits=5, num_layers=1)\n",
        "circ_b = make_trotter_circuit(num_qubits=5, num_layers=2)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "371c4893",
      "metadata": {},
      "outputs": [],
      "source": [
        "multi_pubs = [\n",
        "    (\n",
        "        qiskit.transpile(qci, basis_gates=basis, optimization_level=1),\n",
        "        [avg_magnetization, other_observable],\n",
        "    )\n",
        "    for qci in [circ_a, circ_b]\n",
        "]\n",
        "\n",
        "multi_circ_job = qesem_function.run(\n",
        "    pubs=multi_pubs,\n",
        "    backend_name=backend_name,\n",
        "    options={\n",
        "        \"max_execution_time\": 300,\n",
        "        \"transpilation_level\": \"minimal_with_layout_opt\",\n",
        "        \"default_precision\": 0.1,\n",
        "    },\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 91,
      "id": "92e45737",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "e34565b8-7262-4133-a120-de42ce624a99\n",
            "DONE\n"
          ]
        }
      ],
      "source": [
        "print(multi_circ_job.job_id)\n",
        "print(multi_circ_job.status())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 92,
      "id": "23c61008",
      "metadata": {},
      "outputs": [],
      "source": [
        "multi_circ_result = multi_circ_job.result()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 105,
      "id": "1ae6f8c3",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Multi-pub QESEM results:\n",
            "\n",
            "PUB 0:\n",
            "  Mitigated expectation values: [0.99502406 1.02209332]\n",
            "  Mitigated error bars: [0.00483819 0.00707488]\n",
            "  Unmitigated expectation values: [0.96934286 0.97271429]\n",
            "  Unmitigated error bars: [0.00124855 0.00617294]\n",
            "  Results for each observable:\n",
            "    Circuit 0:\n",
            "      Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())\n",
            "        QESEM mitigated value: 0.9950240647925642 ± 0.004838188086259301\n",
            "        Unmitigated value: 0.9693428571428573 ± 0.0012485470362492692\n",
            "      Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())\n",
            "        QESEM mitigated value: 1.0220933230604674 ± 0.007074884384355636\n",
            "        Unmitigated value: 0.9727142857142859 ± 0.006172939375512439\n",
            "\n",
            "PUB 1:\n",
            "  Mitigated expectation values: [0.98850017 1.02555188]\n",
            "  Mitigated error bars: [0.0077912  0.01672652]\n",
            "  Unmitigated expectation values: [0.93682857 0.95371429]\n",
            "  Unmitigated error bars: [0.00156245 0.00665735]\n",
            "  Results for each observable:\n",
            "    Circuit 0:\n",
            "      Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())\n",
            "        QESEM mitigated value: 0.988500171577252 ± 0.007791203181151346\n",
            "        Unmitigated value: 0.9368285714285716 ± 0.001562451883089579\n",
            "      Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())\n",
            "        QESEM mitigated value: 1.02555188098689 ± 0.016726524388086233\n",
            "        Unmitigated value: 0.9537142857142858 ± 0.006657345655544263\n"
          ]
        }
      ],
      "source": [
        "print(\"Multi-pub QESEM results:\")\n",
        "\n",
        "for pub_idx, pub_result in enumerate(multi_circ_result):\n",
        "    print(f\"\\nPUB {pub_idx}:\")\n",
        "    print(f\"  Mitigated expectation values: {pub_result.data.evs}\")\n",
        "    print(f\"  Mitigated error bars: {pub_result.data.stds}\")\n",
        "    noisy_results = pub_result.metadata[\"noisy_results\"]\n",
        "    print(f\"  Unmitigated expectation values: {noisy_results.evs}\")\n",
        "    print(f\"  Unmitigated error bars: {noisy_results.stds}\")\n",
        "    print(\"  Results for each observable:\")\n",
        "    for circ_idx, circ_results in enumerate(pub_result.metadata[\"results\"]):\n",
        "        print(f\"    Circuit {circ_idx}:\")\n",
        "        for obs_idx, (obs_array, result_dict) in enumerate(circ_results):\n",
        "            print(f\"      Observable {obs_idx}: {obs_array}\")\n",
        "            print(\n",
        "                f\"        QESEM mitigated value: {result_dict['qesem']['value']} ± {result_dict['qesem']['error_bar']}\"\n",
        "            )\n",
        "            print(\n",
        "                f\"        Unmitigated value: {result_dict['unmitigated']['value']} ± {result_dict['unmitigated']['error_bar']}\"\n",
        "            )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8f28d826",
      "metadata": {},
      "source": [
        "<span id=\"quasi-probabilistic-error-tuning-qet-example\" />\n",
        "\n",
        "### Ejemplo de ajuste de errores cuasiprobabilístico (QET)\n",
        "\n",
        "El ajuste de errores cuasiprobabilístico (QET) requiere valores esperados en factores de escala de ruido seleccionados. Esto resulta útil para estudios de escalado de ruido personalizados y flujos de trabajo de extrapolación con ruido cero. La escala `1.0` es el nivel físico de ruido; los valores comprendidos entre `0.0` y `1.0` reducen parcialmente el ruido, mientras que los valores superiores `1.0` a lo amplifican.\n",
        "\n",
        "Para utilizar QET con la función de Qiskit, pasa un diccionario como precisión de « PUB ». El diccionario asocia cada escala de ruido solicitada a su precisión objetivo. Los resultados del factor de escala devueltos se almacenan en `noise_scaling.results_with_REM` e incluyen la mitigación de la lectura. Por lo tanto, el punto de escala `1.0` no es idéntico al valor sin mitigación, ya que `1.0` incluye la mitigación de la lectura, mientras `unmitigated` que no la incluye.\n",
        "\n",
        "Cuando se solicita una escala, QESEM también devuelve la escala complementaria en torno a `1.0` sin un consumo adicional de QPU. Por ejemplo, al solicitar `0.5` también se puede obtener `1.5`, y al solicitar `1.3` también se puede obtener `0.7`. No se garantiza la precisión de la escala complementaria.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 88,
      "id": "723cdf95",
      "metadata": {},
      "outputs": [],
      "source": [
        "noise_scale_precision = {0.5: 0.15, 1.3: 0.2}\n",
        "\n",
        "qet_job = qesem_function.run(\n",
        "    pubs=[\n",
        "        (\n",
        "            circ,\n",
        "            [avg_magnetization, other_observable],\n",
        "            None,\n",
        "            noise_scale_precision,\n",
        "        )\n",
        "    ],\n",
        "    backend_name=backend_name,\n",
        "    options={\"max_execution_time\": 300},\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 95,
      "id": "d68a015c",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "8195fa58-f037-4651-8715-36ce1cdc5521\n",
            "DONE\n"
          ]
        }
      ],
      "source": [
        "print(qet_job.job_id)\n",
        "print(qet_job.status())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 96,
      "id": "927d8543",
      "metadata": {},
      "outputs": [],
      "source": [
        "qet_result = qet_job.result()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 104,
      "id": "1c9ba079",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QET noise-scaling results:\n",
            "\n",
            "PUB 0:\n",
            "  Unmitigated expectation values: [0.97822857 0.96171429]\n",
            "  Unmitigated error bars: [0.00123812 0.00672958]\n",
            "  Results for each observable:\n",
            "    Circuit 0:\n",
            "      Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())\n",
            "        Scaling method: QESEM\n",
            "        Results with Readout mitigation (REM):\n",
            "          Scale factor 0.5: 0.9938730340199383 ± 0.0032116907357568275\n",
            "          Scale factor 0.7: 0.9963976191853445 ± 0.00036300258869586616\n",
            "          Scale factor 1.0: 0.9898115079506586 ± 0.0012525947426560995\n",
            "          Scale factor 1.3: 0.9864667065580341 ± 0.002633221613518526\n",
            "          Scale factor 1.5: 0.9838755527197551 ± 0.002948417797996015\n",
            "      Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())\n",
            "        Scaling method: QESEM\n",
            "        Results with Readout mitigation (REM):\n",
            "          Scale factor 0.5: 1.0006538544450332 ± 0.002121742014777343\n",
            "          Scale factor 0.7: 1.0004159801523036 ± 0.0021671375357823794\n",
            "          Scale factor 1.0: 0.9898058846339917 ± 0.00690183710903159\n",
            "          Scale factor 1.3: 0.9948946719997267 ± 0.002146532859610311\n",
            "          Scale factor 1.5: 0.9927220368192772 ± 0.0020875057190323882\n"
          ]
        }
      ],
      "source": [
        "print(\"QET noise-scaling results:\")\n",
        "\n",
        "for pub_idx, pub_result in enumerate(qet_result):\n",
        "    print(f\"\\nPUB {pub_idx}:\")\n",
        "    noisy_results = pub_result.metadata[\"noisy_results\"]\n",
        "    print(f\"  Unmitigated expectation values: {noisy_results.evs}\")\n",
        "    print(f\"  Unmitigated error bars: {noisy_results.stds}\")\n",
        "    print(\"  Results for each observable:\")\n",
        "    for circ_idx, circ_results in enumerate(pub_result.metadata[\"results\"]):\n",
        "        print(f\"    Circuit {circ_idx}:\")\n",
        "        for obs_idx, (obs_array, result_dict) in enumerate(circ_results):\n",
        "            print(f\"      Observable {obs_idx}: {obs_array}\")\n",
        "            noise_scaling = result_dict[\"noise_scaling\"]\n",
        "            print(\n",
        "                f\"        Scaling method: {noise_scaling['scaling_method']}\"\n",
        "            )\n",
        "            print(\"        Results with Readout mitigation (REM):\")\n",
        "            for rem_result in sorted(\n",
        "                (\n",
        "                    item\n",
        "                    for item in noise_scaling[\"results_with_REM\"]\n",
        "                    if item[\"scale\"] != 0.0\n",
        "                ),\n",
        "                key=lambda item: item[\"scale\"],\n",
        "            ):\n",
        "                print(\n",
        "                    f\"          Scale factor {rem_result['scale']}: {rem_result['value']} ± {rem_result['error_bar']}\"\n",
        "                )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "35aed54a",
      "metadata": {},
      "source": [
        "<span id=\"fetch-error-messages\" />\n",
        "\n",
        "## Obtener mensajes de error\n",
        "\n",
        "Si el estado de tu carga de trabajo es ERROR, utiliza `job.result()` para obtener el mensaje de error de la siguiente manera:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "d95a3f30",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(2,), dtype=float64>), stds=np.ndarray(<shape=(2,), dtype=float64>), shape=(2,)), metadata={'gate_fidelities': {'CZ': 0.9979444718552628, 'ID1Q': 0.9991994239814883}, 'total_shots': 498600, 'mitigation_shots': 223400, 'transpiled_circs': [{'circuit': 'OPENQASM 3.0;\\ninclude \"stdgates.inc\";\\nbit[76] c0;\\nqubit[76] q0;\\nrx(0) q0[54];\\nrx(0) q0[59];\\nrx(0) q0[75];\\nrz(pi/2) q0[54];\\nrz(pi/2) q0[59];\\nrz(pi/2) q0[75];\\nrx(pi/2) q0[54];\\nr... (truncated 3771 characters)\n"
          ]
        }
      ],
      "source": [
        "# Get the result and truncate for readability\n",
        "result = sample_job.result()\n",
        "result_str = str(result)\n",
        "max_length = 500  # Adjust this value as necessary\n",
        "\n",
        "if len(result_str) > max_length:\n",
        "    truncated = (\n",
        "        result_str[:max_length]\n",
        "        + f\"... (truncated {len(result_str) - max_length} characters)\"\n",
        "    )\n",
        "else:\n",
        "    truncated = result_str\n",
        "\n",
        "print(truncated)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e9ec2e67",
      "metadata": {},
      "source": [
        "<span id=\"get-support\" />\n",
        "\n",
        "## Obtener soporte\n",
        "\n",
        "El equipo de asistencia de Qedma está aquí para ayudarle Si tiene algún problema o pregunta sobre el uso de la función Qiskit de QESEM, no dude en ponerse en contacto con nosotros. Nuestro amable y experto personal de asistencia está a su disposición para ayudarle con cualquier duda o consulta técnica que pueda tener.\n",
        "\n",
        "Puede enviarnos un correo electrónico a [support@qedma.com](mailto:support@qedma.com) si necesita ayuda. Por favor, incluya tantos detalles como sea posible sobre el problema que está experimentando para ayudarnos a proporcionar una respuesta rápida y precisa. También puede ponerse en contacto con su representante POC de Qedma por correo electrónico o por teléfono.\n",
        "\n",
        "Para ayudarnos a atenderle con mayor eficacia, le rogamos que nos facilite la siguiente información cuando se ponga en contacto con nosotros:\n",
        "\n",
        "* Descripción detallada del problema\n",
        "* ID de trabajo\n",
        "* Cualquier mensaje o código de error relevante\n",
        "\n",
        "Nos comprometemos a proporcionarle una asistencia rápida y eficaz para garantizarle la mejor experiencia posible con nuestra función Qiskit.\n",
        "\n",
        "Siempre buscamos mejorar nuestro producto y agradecemos sus sugerencias Si tiene alguna idea sobre cómo podemos mejorar nuestros servicios o funciones que le gustaría ver, envíenos sus comentarios a [support@qedma.com](mailto:support@qedma.com).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5a6a25c8",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximos pasos\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendaciones\">\n",
        "  * [Solicitar acceso a Qedma QESEM](/functions?id=qedma-qesem).\n",
        "  * Consulta la [referencia](/docs/api/functions/qedma-qesem) de la API de esta función de Qiskit.\n",
        "  * Prueba el tutorial «[Simulación de un modelo de Ising de campo inclinado 2D con la función QESEM](/docs/tutorials/qedma-2d-ising-with-qesem) ».\n",
        "  * Revisión [Aharonov, D., et al. (2025). Mitigación de errores fiable y de alta precisión para circuitos cuánticos a escala industrial. arXiv Preimpresión arXiv:2508.10997](https://arxiv.org/pdf/2508.10997).\n",
        "  * Reseña [Aharonov, D., et al. (2025). Mitigación de los errores lógicos basada en el reconocimiento de síndromes. arXiv Preimpresión arXiv:2508.10997](https://arxiv.org/pdf/2508.10997).\n",
        "  * Reseña [Aharonov, D., et al. (2025). Sobre la importancia de la mitigación de errores en la computación cuántica. arXiv Preimpresión arXiv:2512.23810](https://arxiv.org/abs/2512.23810).\n",
        "  * Revisión [Bauman, N. P., et al. (2025). Teoría del plegamiento descendente de clústeres acoplados en simulaciones de sistemas químicos en hardware cuántico. arXiv Preimpresión arXiv:2507.01199](https://arxiv.org/pdf/2507.01199).\n",
        "  * Reseña [Goldack, M., et al. (2026). Cálculo de las propiedades estadísticas de los campos de velocidad en el hardware cuántico actual. arXiv Preimpresión arXiv:2601.10166](https://arxiv.org/pdf/2601.10166).\n",
        "  * Reseña [Sakuma, R., et al. (2026). Análisis de la simetría de grupos puntuales de funciones de onda de muchos electrones en un ordenador cuántico arXiv preimpresión arXiv:2605.24824](https://arxiv.org/abs/2605.24824).\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": 5
}