{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "066d7e4d-a975-4519-b56f-095f861be3ac",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Entradas y salidas del estimador\"\n",
        "description: \"Comprender el formato de entrada y salida de la primitiva Estimator\"\n",
        "---\n",
        "\n",
        "<span id=\"estimator-inputs-and-outputs\" />\n",
        "\n",
        "# Entradas y salidas del estimador\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "23e7dff0-fde5-4c2d-89c2-fc5ab99240fe",
      "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": "90d0c1e0-28e7-48da-a35f-6016fddea82c",
      "metadata": {},
      "source": [
        "Esta página ofrece una descripción general de las entradas y salidas de la primitiva « Qiskit Runtime Estimator», que ejecuta cargas de trabajo en recursos de computación de IBM Quantum®. Estimator te permite definir de forma eficiente cargas de trabajo vectorizadas mediante una estructura de datos denominada [**« PUB » ()**](/docs/guides/primitive-input-output#pubs). Se utilizan como entradas para el [`run()`](/docs/api/qiskit-ibm-runtime/estimator-v2#run) método de la primitiva Estimator, que ejecuta la carga de trabajo definida como un trabajo. A continuación, una vez finalizado el trabajo, los resultados se devuelven en un formato que depende tanto de los PUB utilizados como de las opciones de ejecución especificadas en la primitiva.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "83a5fdd8-6547-47c7-9441-a7458edc7896",
      "metadata": {},
      "source": [
        "<span id=\"inputs\" />\n",
        "\n",
        "## Entradas\n",
        "\n",
        "Cada archivo « PUB » tiene este formato:\n",
        "\n",
        "(`<single circuit>`, `<one or more observables>`, `<optional one or more parameter values>`, `<optional precision>`),\n",
        "\n",
        "El parámetro opcional `parameter values` puede ser una lista o un único parámetro. Los elementos de los observables y los valores de los parámetros se combinan siguiendo las reglas de difusión de NumPy, tal y como se describe en el tema [«Entradas y salidas primitivas»](primitive-input-output#broadcasting-rules), y se devuelve una estimación del valor esperado para cada elemento de la forma difundida.\n",
        "\n",
        "<Admonition types=\"note\">\n",
        "  Si la entrada contiene medidas, estas se ignoran.\n",
        "</Admonition>\n",
        "\n",
        "En el caso de la primitiva «Estimator», un « PUB » puede contener como máximo cuatro valores:\n",
        "\n",
        "* Un único elemento `QuantumCircuit`, que puede contener uno o más [`Parameter`](/docs/api/qiskit/qiskit.circuit.Parameter) objetos\n",
        "* Una lista de uno o varios observables, que especifican los valores esperados que se van a estimar, organizados en una matriz (por ejemplo, un único observable representado como una matriz de dimensión 0, una lista de observables como una matriz de dimensión 1, y así sucesivamente). Los datos pueden estar en cualquiera de los siguientes `ObservablesArrayLike` formatos: `Pauli` `SparsePauliOp`, `PauliList`,, o `str`.\n",
        "  <Admonition type=\"note\" title=\"Variables de desplazamiento\">\n",
        "    * Con [este método](/docs/api/qiskit/qiskit.quantum_info.PauliList#group_qubit_wise_commuting) se agrupan los observables de desplazamiento que se encuentran **en el mismo « PUB** ».\n",
        "    * Las variables observables de desplazamiento en diferentes PUB, aunque compartan el mismo circuito, no se estiman utilizando la misma medición. Cada PUB representa una base de medición diferente y, por lo tanto, se requieren mediciones independientes para cada PUB.\n",
        "    * Para garantizar que las variables observables relacionadas con los desplazamientos se calculen utilizando la misma medida, agrúpalas en el mismo « PUB ».\n",
        "  </Admonition>\n",
        "* Un conjunto de valores de parámetros con los que se va a vincular el circuito. Esto se puede especificar como un único objeto similar a una matriz, en el que el último índice corresponde a los `Parameter` objetos del circuito, o bien se puede omitir (o, lo que es lo mismo, establecerse en `None`) si el circuito no tiene `Parameter` objetos.\n",
        "* (Opcional) Una precisión objetivo para los valores esperados que se van a estimar\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "846b3109-02a1-4783-ad3f-1c22f753c324",
      "metadata": {},
      "source": [
        "***\n",
        "\n",
        "El siguiente código muestra un conjunto de entradas vectorizadas para la `Estimator` primitiva y las ejecuta en un backend de IBM® como un único `RuntimeJobV2 ` objeto.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "2f50a9f5-2cc1-4d83-9fe1-1b3a8be0d766",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.circuit import (\n",
        "    Parameter,\n",
        "    QuantumCircuit,\n",
        ")\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "\n",
        "from qiskit_ibm_runtime import (\n",
        "    QiskitRuntimeService,\n",
        "    EstimatorV2 as Estimator,\n",
        ")\n",
        "\n",
        "import numpy as np\n",
        "\n",
        "# Instantiate runtime service and get\n",
        "# the least busy backend\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "\n",
        "# Define a circuit with two parameters.\n",
        "circuit = QuantumCircuit(2)\n",
        "circuit.h(0)\n",
        "circuit.cx(0, 1)\n",
        "circuit.ry(Parameter(\"a\"), 0)\n",
        "circuit.rz(Parameter(\"b\"), 0)\n",
        "circuit.cx(0, 1)\n",
        "circuit.h(0)\n",
        "\n",
        "# Transpile the circuit\n",
        "pm = generate_preset_pass_manager(optimization_level=1, backend=backend)\n",
        "transpiled_circuit = pm.run(circuit)\n",
        "layout = transpiled_circuit.layout\n",
        "\n",
        "# Now define a sweep over parameter values, the last axis of dimension 2 is\n",
        "# for the two parameters \"a\" and \"b\"\n",
        "params = np.vstack(\n",
        "    [\n",
        "        np.linspace(-np.pi, np.pi, 100),\n",
        "        np.linspace(-4 * np.pi, 4 * np.pi, 100),\n",
        "    ]\n",
        ").T\n",
        "\n",
        "# Define three observables. The inner length-1 lists cause this array of\n",
        "# observables to have shape (3, 1), rather than shape (3,) if they were\n",
        "# omitted.\n",
        "observables = [\n",
        "    [SparsePauliOp([\"XX\", \"IY\"], [0.5, 0.5])],\n",
        "    [SparsePauliOp(\"XX\")],\n",
        "    [SparsePauliOp(\"IY\")],\n",
        "]\n",
        "# Apply the same layout as the transpiled circuit.\n",
        "observables = [\n",
        "    [observable.apply_layout(layout) for observable in observable_set]\n",
        "    for observable_set in observables\n",
        "]\n",
        "\n",
        "# Estimate the expectation value for all 300 combinations of observables\n",
        "# and parameter values, where the pub result will have shape (3, 100).\n",
        "#\n",
        "# This shape is due to our array of parameter bindings having shape\n",
        "# (100, 2), combined with our array of observables having shape (3, 1).\n",
        "estimator_pub = (transpiled_circuit, observables, params)\n",
        "\n",
        "# Instantiate the new Estimator object, then run the transpiled circuit\n",
        "# using the set of parameters and observables.\n",
        "estimator = Estimator(mode=backend)\n",
        "job = estimator.run([estimator_pub])\n",
        "result = job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "90dccb20-1848-4367-a12d-434110ad5a5c",
      "metadata": {},
      "source": [
        "<span id=\"outputs\" />\n",
        "\n",
        "## Resultados\n",
        "\n",
        "Una vez que se envían uno o varios PUB a una QPU para su ejecución y un trabajo se completa con éxito, los datos se devuelven como un objeto [`PrimitiveResult`](/docs/api/qiskit/qiskit.primitives.PrimitiveResult) contenedor al que se accede llamando al `RuntimeJobV2.result()` método.\n",
        "\n",
        "El objeto `PrimitiveResult` contiene una lista iterable de [`PubResult`](/docs/api/qiskit/qiskit.primitives.PubResult) objetos que recogen los resultados de la ejecución de cada `PUB`.\n",
        "\n",
        "Cada elemento de esta lista se corresponde con cada PUB enviado al método de la `run()` primitiva (por ejemplo, un trabajo enviado con 20 PUBs devolverá un `PrimitiveResult` objeto que contiene una lista de 20 `PubResult` objetos, uno correspondiente a cada PUB ).\n",
        "\n",
        "Cada primitiva `PubResult` del estimador contiene, como mínimo, una matriz de valores esperados (`PubResult.data.evs`) y las desviaciones estándar asociadas (ya sea `PubResult.data.stds` o, `PubResult.data.ensemble_standard_error` dependiendo del `resilience_level` utilizado), pero puede contener más datos en función de las opciones de mitigación de errores que se hayan especificado.\n",
        "\n",
        "Cada `PubResult` objeto posee un atributo `data` y un `metadata` atributo.\n",
        "\n",
        "* El `data` atributo es un campo personalizado [`DataBin`](/docs/api/qiskit/qiskit.primitives.DataBin) que contiene los valores de medición reales, las desviaciones estándar, etc.\n",
        "* El `DataBin` presenta diversos atributos en función de la forma o estructura del objeto « PUB » asociado, así como de las opciones de mitigación de errores especificadas por la primitiva utilizada para enviar el trabajo (por ejemplo, [ZNE](/docs/guides/error-mitigation-and-suppression-techniques#zero-noise-extrapolation-zne) o [PEC](/docs/guides/error-mitigation-and-suppression-techniques#probabilistic-error-cancellation-pec) ).\n",
        "* El `metadata` atributo contiene información sobre el tiempo de ejecución y las opciones de mitigación de errores utilizadas (como se explica más adelante en la sección [«Metadatos del resultado»](#result-metadata) de esta página).\n",
        "\n",
        "A continuación se ofrece un esquema visual de la estructura `PrimitiveResult` de datos de la salida del Estimador:\n",
        "\n",
        "```\n",
        "└── PrimitiveResult\n",
        "    ├── PubResult[0]\n",
        "    │   ├── metadata\n",
        "    │   └── data  ## In the form of a DataBin object\n",
        "    │       ├── evs\n",
        "    │       │   └── List of estimated expectation values in the shape\n",
        "    |       |         specified by the first pub\n",
        "    │       └── stds\n",
        "    │           └── List of calculated standard deviations in the\n",
        "    |                 same shape as above\n",
        "    ├── PubResult[1]\n",
        "    |   ├── metadata\n",
        "    |   └── data  ## In the form of a DataBin object\n",
        "    |       ├── evs\n",
        "    |       │   └── List of estimated expectation values in the shape\n",
        "    |       |        specified by the second pub\n",
        "    |       └── stds\n",
        "    |           └── List of calculated standard deviations in the\n",
        "    |                same shape as above\n",
        "    ├── ...\n",
        "    ├── ...\n",
        "    └── ...\n",
        "```\n",
        "\n",
        "En pocas palabras, una tarea devuelve un `PrimitiveResult` objeto y contiene una lista de uno o más `PubResult` objetos. A continuación, estos `PubResult` objetos almacenan los datos de medición de cada « PUB » que se haya enviado al trabajo.\n",
        "\n",
        "El siguiente fragmento de código describe el formato `PrimitiveResult` (y los elementos asociados `PubResult`) del trabajo creado anteriormente.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "53a4d5ae-109b-452b-bbc5-2d7940c5182c",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The result of the submitted job had 1 PUBs and has a value:\n",
            " PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(3, 100), dtype=float64>), stds=np.ndarray(<shape=(3, 100), dtype=float64>), ensemble_standard_error=np.ndarray(<shape=(3, 100), dtype=float64>), shape=(3, 100)), 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",
            "\n",
            "The associated PubResult of this job has the following data bins:\n",
            " {result[0].data}\n",
            "\n",
            "And this DataBin has attributes: dict_keys(['evs', 'stds', 'ensemble_standard_error'])\n",
            "Recall that this shape is due to our array of parameter binding setshaving shape (100, 2), where 2 is the number of parameters in the circuit, combined with our array of observables having shape (3, 1). \n",
            "\n",
            "The expectation values measured from this PUB are: \n",
            "{result[0].data.evs}\n",
            "\n"
          ]
        }
      ],
      "source": [
        "print(\n",
        "    f\"The result of the submitted job had {len(result)} \"\n",
        "    f\"PUBs and has a value:\\n {result}\\n\"\n",
        ")\n",
        "print(\n",
        "    \"The associated PubResult of this job has the following data bins:\\n \"\n",
        "    \"{result[0].data}\\n\"\n",
        ")\n",
        "print(f\"And this DataBin has attributes: {result[0].data.keys()}\")\n",
        "print(\n",
        "    \"Recall that this shape is due to our array of parameter binding sets\"\n",
        "    \"having shape (100, 2), where 2 is the number of parameters in the \"\n",
        "    \"circuit, combined with our array of observables having shape (3, 1). \\n\"\n",
        ")\n",
        "with np.printoptions(threshold=200):\n",
        "    print(\n",
        "        \"The expectation values measured from this PUB are: \\n\"\n",
        "        \"{result[0].data.evs}\\n\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "000ade51-d940-45f9-84ea-16ad283a930f",
      "metadata": {},
      "source": [
        "<span id=\"how-the-estimator-primitive-calculates-error\" />\n",
        "\n",
        "#### Cómo calcula el error la primitiva Estimator\n",
        "\n",
        "Además de la estimación de la media de las variables observables pasadas en los PUB de entrada (el `evs` campo de la `DataBin`), el estimador también intenta proporcionar una estimación del error asociado a esos valores esperados. Todas las consultas de Estimator rellenarán el `stds` campo con una cantidad equivalente al error estándar de la media para cada valor esperado, pero algunas opciones de mitigación de errores proporcionan información adicional, como `ensemble_standard_error`.\n",
        "\n",
        "Consideremos una única variable observable $\\mathcal{O}$. En ausencia de [ZNE](/docs/guides/error-mitigation-and-suppression-techniques#zero-noise-extrapolation-zne), podemos considerar que cada iteración de la ejecución del estimador proporciona una estimación puntual del valor esperado $\\langle \\mathcal{O} \\rangle$. Si las estimaciones puntuales forman un vector `Os`, entonces el valor devuelto en `ensemble_standard_error` es equivalente a lo siguiente (donde $\\sigma_{\\mathcal{O}}$ es la [desviación estándar de la](/docs/api/qiskit/qiskit.primitives.BackendEstimatorV2) estimación del valor esperado y $N_{shots}$ es el número de iteraciones):\n",
        "\n",
        "$\\frac{ \\sigma_{\\mathcal{O}} }{ \\sqrt{N_{shots}} },$\n",
        "\n",
        "que considera todos los planos como parte de un único conjunto. Si has solicitado [el giro](/docs/guides/error-mitigation-and-suppression-techniques#pauli-twirling) de puertas (`twirling.enable_gates = True`), puedes clasificar las estimaciones puntuales de $\\langle \\mathcal{O} \\rangle$ en conjuntos que compartan un giro común. Denominemos a estos conjuntos de estimaciones `O_twirls`, y hay `num_randomizations` (número de giros) de ellos. Entonces `stds` es el error estándar de la media de `O_twirls`, tal y como se indica en\n",
        "\n",
        "$\\frac{ \\sigma_{\\mathcal{O}} }{ \\sqrt{N_{twirls}} },$\n",
        "\n",
        "donde $\\sigma_{\\mathcal{O}}$ es la desviación estándar de `O_twirls` y $N_{twirls}$ es el número de giros. Cuando no se activa el efecto giratorio, `stds` y `ensemble_standard_error` son iguales.\n",
        "\n",
        "Si se activa ZNE, los parámetros `stds` descritos anteriormente se convierten en coeficientes de un modelo de regresión no lineal para un modelo de extrapolación. Lo que finalmente se devuelve en este `stds` caso es la incertidumbre del modelo de ajuste evaluada con un factor de ruido igual a cero. Cuando el ajuste es deficiente o existe una gran incertidumbre en el ajuste, el valor obtenido `stds` puede llegar a ser muy elevado. Cuando se activa ZNE, `pub_result.data.evs_noise_factors` y también `pub_result.data.stds_noise_factors` se rellenan, de modo que puedas realizar tu propia extrapolación.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c4341184-a41a-4442-bc05-838c90ea93b8",
      "metadata": {},
      "source": [
        "<span id=\"result-metadata\" />\n",
        "\n",
        "## Metadatos del resultado\n",
        "\n",
        "Además de los resultados de la ejecución, tanto el objeto `PrimitiveResult` como `PubResult` el contienen un atributo de metadatos sobre el trabajo que se envió. Los metadatos que contienen información sobre todos los PUB enviados (como las distintas [opciones de tiempo de ejecución](/docs/api/qiskit-ibm-runtime/options) disponibles) se encuentran en el `PrimitiveResult.metatada`, mientras que los metadatos específicos de cada PUB se encuentran en `PubResult.metadata`.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  En el campo de metadatos, las implementaciones de primitivas pueden devolver cualquier información sobre la ejecución que les resulte relevante, y no hay pares clave-valor garantizados por la primitiva base. Por lo tanto, los metadatos devueltos pueden variar según la implementación de la primitiva.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "626ba203-44e2-4b8f-b04d-04388b8b1fa1",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The metadata of the PrimitiveResult is:\n",
            "'dynamical_decoupling' : {'enable': False, 'sequence_type': 'XX', 'extra_slack_distribution': 'middle', 'scheduling_method': 'alap'},\n",
            "'twirling' : {'enable_gates': False, 'enable_measure': True, 'num_randomizations': 'auto', 'shots_per_randomization': 'auto', 'interleave_randomizations': True, 'strategy': 'active-accum'},\n",
            "'resilience' : {'measure_mitigation': True, 'zne_mitigation': False, 'pec_mitigation': False},\n",
            "'version' : 2,\n",
            "\n",
            "The metadata of the PubResult result is:\n",
            "'shots' : 4096,\n",
            "'target_precision' : 0.015625,\n",
            "'circuit_metadata' : {},\n",
            "'resilience' : {},\n",
            "'num_randomizations' : 32,\n"
          ]
        }
      ],
      "source": [
        "# Print out the results metadata\n",
        "print(\"The metadata of the PrimitiveResult is:\")\n",
        "for key, val in result.metadata.items():\n",
        "    print(f\"'{key}' : {val},\")\n",
        "\n",
        "print(\"\\nThe metadata of the PubResult result is:\")\n",
        "for key, val in result[0].metadata.items():\n",
        "    print(f\"'{key}' : {val},\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "celltoolbar": "Raw Cell Format",
    "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
}