{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "552b1077",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Ejecute su primer circuito en hardware\"\n",
        "description: \"Empiece a utilizar Qiskit con hardware de IBM Quantum en este ejemplo Hello World\"\n",
        "---\n",
        "\n",
        "<span id=\"run-your-first-circuit-on-hardware\" />\n",
        "\n",
        "# Ejecute su primer circuito en hardware\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7cc19a86-a234-4220-bb4f-d66d3834e0c3",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "{/*\n",
        "  DO NOT EDIT THIS CELL!!!\n",
        "  This cell's content is generated automatically by a script. Anything you add\n",
        "  here will be removed next time the notebook is run. To add new content, create\n",
        "  a new cell before or after this one.\n",
        "  */}\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Versiones del paquete\">\n",
        "    El código de esta página se ha desarrollado siguiendo los siguientes requisitos.\n",
        "    Recomendamos utilizar estas versiones o posteriores.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.0\n",
        "    qiskit-ibm-runtime~=0.47.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1a3c196d-545d-417f-b34e-fa422aa9a394",
      "metadata": {},
      "source": [
        "Este ejemplo consta de dos partes. Primero crearás un sencillo programa cuántico «Hola mundo» y lo ejecutarás en una unidad de procesamiento cuántico (QPU).  Dado que la investigación cuántica real requiere programas mucho más robustos, en la segunda sección ( [Escalado a un gran número de qubits](#scale-to-large-numbers-of-qubits) ), ampliarás el programa simple hasta alcanzar un nivel de utilidad.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7b65f7e0",
      "metadata": {},
      "source": [
        "<span id=\"install-and-authenticate\" />\n",
        "\n",
        "## Instalar y autenticar\n",
        "\n",
        "1. Si aún no ha instalado Qiskit, consulte las instrucciones de la guía [de inicio rápido](/docs/guides/quick-start).\n",
        "\n",
        "   * Instalar Qiskit Runtime para ejecutar trabajos en hardware cuántico:\n",
        "\n",
        "     ```bash\n",
        "     pip install qiskit-ibm-runtime\n",
        "     ```\n",
        "\n",
        "   * Configure un entorno para ejecutar cuadernos Jupyter localmente:\n",
        "\n",
        "     ```bash\n",
        "     pip install jupyter\n",
        "     ```\n",
        "\n",
        "2. Configure su autenticación para acceder al hardware cuántico a través del [plan](/docs/guides/plans-overview#open-plan) gratuito Open Plan.\n",
        "\n",
        "   (Si ha recibido una invitación por correo electrónico para unirse a una cuenta, siga los [pasos para usuarios invitados](/docs/guides/cloud-setup-invited) )\n",
        "\n",
        "   * Vaya a [IBM Quantum Platform](/) para iniciar sesión o crear una cuenta.\n",
        "     <Admonition type=\"note\" title=\"Importante\">\n",
        "       Si se conecta a través de un servidor proxy, debe utilizar Qiskit Runtime v0.44.0 o una versión posterior.\n",
        "     </Admonition>\n",
        "\n",
        "   * Genere su clave API (también denominada *token* API) en el [panel de control](/) y, a continuación, cópiela en una ubicación segura.\n",
        "\n",
        "   * Vaya a la página [Instancias](/instances) y busque la instancia que desea utilizar. Pase el cursor sobre su CRN y haga clic para copiarlo.\n",
        "\n",
        "   * Guarda tus credenciales localmente con este código:\n",
        "\n",
        "     ```python\n",
        "     from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "     QiskitRuntimeService.save_account(\n",
        "         # For `token`, use the 44-character API_KEY you created\n",
        "         # and saved from the IBM Quantum Platform Home dashboard\n",
        "         token=\"<your-api-key>\",\n",
        "         instance=\"<CRN>\", # Optional\n",
        "     )\n",
        "     ```\n",
        "\n",
        "3. Ahora puede utilizar este Python código cada vez que desee autenticarse en el Qiskit Runtime servicio:\n",
        "   ```python\n",
        "   from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "   # Run every time you need the service\n",
        "   service = QiskitRuntimeService()\n",
        "   ```\n",
        "\n",
        "<Admonition type=\"info\" title=\"¿No utiliza un entorno de Python confianza?\">\n",
        "  Si utiliza un ordenador público u otro entorno no seguro, siga las [instrucciones de autenticación manual](/docs/guides/cloud-setup-untrusted) para mantener seguras sus credenciales de autenticación.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "80471a0a",
      "metadata": {},
      "source": [
        "<span id=\"create-and-run-a-simple-quantum-program\" />\n",
        "\n",
        "## Crear y ejecutar un programa cuántico sencillo\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "85fe979e",
      "metadata": {
        "raw_mimetype": "text/restructuredtext"
      },
      "source": [
        "Los cuatro pasos para escribir un programa cuántico utilizando patrones Qiskit son:\n",
        "\n",
        "1. Asigne el problema a un formato cuántico nativo.\n",
        "\n",
        "2. Optimizar los circuitos y los operadores.\n",
        "\n",
        "3. Ejecutar utilizando una función primitiva cuántica.\n",
        "\n",
        "4. Analice los resultados.\n",
        "\n",
        "<span id=\"step-1-map-the-problem-to-a-quantum-native-format\" />\n",
        "\n",
        "### Paso 1. Asignar el problema a un formato cuántico nativo\n",
        "\n",
        "En un programa cuántico, *los circuitos cuánticos* son el formato nativo en el que se representan las instrucciones cuánticas, y *los operadores* representan los observables que se van a medir. Al crear un circuito, normalmente se crea un nuevo [`QuantumCircuit`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#quantumcircuit-class) objeto y luego se le añaden instrucciones en secuencia.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "21f7a26c",
      "metadata": {},
      "source": [
        "La siguiente celda de código crea un circuito que produce un *estado Bell,* que es un estado en el que dos qubits están completamente entrelazados entre sí.\n",
        "\n",
        "<Admonition type=\"note\" title=\"Nota: orden de los bits\">\n",
        "  El Qiskit SDK utiliza la numeración de bits LSb 0, donde el $n^{th}$ dígito tiene un valor $1 \\ll n$ o $2^n$. Para obtener más detalles, consulte [el Qiskit SDK](/docs/guides/bit-ordering) tema Ordenación de bits en el.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "930ca3b6",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/hello-world/extracted-outputs/930ca3b6-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "from qiskit_ibm_runtime import EstimatorOptions\n",
        "from qiskit_ibm_runtime import EstimatorV2 as Estimator\n",
        "from matplotlib import pyplot as plt\n",
        "# Uncomment the next line if you want to use a simulator:\n",
        "# from qiskit_ibm_runtime.fake_provider import FakeBelemV2\n",
        "\n",
        "\n",
        "# Create a new circuit with two qubits\n",
        "qc = QuantumCircuit(2)\n",
        "\n",
        "# Add a Hadamard gate to qubit 0\n",
        "qc.h(0)\n",
        "\n",
        "# Perform a controlled-X gate on qubit 1, controlled by qubit 0\n",
        "qc.cx(0, 1)\n",
        "\n",
        "# Return a drawing of the circuit using MatPlotLib (\"mpl\").\n",
        "# These guides are written by using Jupyter notebooks, which\n",
        "# display the output of the last line of each cell.\n",
        "# If you're running this in a script, use `print(qc.draw())` to\n",
        "# print a text drawing.\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0c957de9",
      "metadata": {
        "raw_mimetype": "text/restructuredtext"
      },
      "source": [
        "Consulte [`QuantumCircuit`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#quantumcircuit-class) la documentación para ver todas las operaciones disponibles.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f3ef4248-7938-44c1-85f1-edc997f0edcd",
      "metadata": {},
      "source": [
        "Al crear circuitos cuánticos, también hay que tener en cuenta qué tipo de datos se desea obtener tras la ejecución. Qiskit ofrece dos formas de obtener datos: puedes obtener resultados de muestreo para un conjunto de qubits que elijas medir, o puedes obtener el valor esperado de una observable. Prepara tu carga de trabajo para medir tu circuito de una de estas dos formas con Qiskit primitives (se explica con detalle en [el paso 3](#step-3-execute-using-the-quantum-primitives) ).\n",
        "\n",
        "Este ejemplo mide los valores esperados utilizando el `qiskit.quantum_info` submódulo, que se especifica mediante operadores (objetos matemáticos utilizados para representar una acción o proceso que cambia un estado cuántico). La siguiente celda de código crea seis operadores de Pauli de dos qubits: `IZ`, `IX`, `ZI` `XI`, `ZZ`, y `XX`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "c57b261c-b757-4432-beab-61b526c98a41",
      "metadata": {
        "tags": []
      },
      "outputs": [],
      "source": [
        "# Set up six different observables.\n",
        "\n",
        "observables_labels = [\"IZ\", \"IX\", \"ZI\", \"XI\", \"ZZ\", \"XX\"]\n",
        "observables = [SparsePauliOp(label) for label in observables_labels]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "47150779",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\" title=\"Notación del operador\">\n",
        "  Aquí, algo como el `ZZ` operador es una abreviatura del producto tensorial $Z\\otimes Z$, lo que significa medir Z en el qubit 1 y Z en el qubit 0 juntos, y obtener información sobre la correlación entre el qubit 1 y el qubit 0. Los valores esperados como este también se suelen escribir como $\\langle Z_1 Z_0 \\rangle$.\n",
        "\n",
        "  Si el estado está entrelazado, entonces la medición de $\\langle Z_1 Z_0 \\rangle$ debería ser diferente de la medición de $\\langle I_1 \\otimes Z_0 \\rangle \\langle Z_1 \\otimes I_0 \\rangle$. Para el estado entrelazado específico creado por nuestro circuito descrito anteriormente, la medición de $\\langle Z_1 Z_0 \\rangle$ debería ser 1 y la medición de $\\langle I_1 \\otimes Z_0 \\rangle \\langle Z_1 \\otimes I_0 \\rangle$ debería ser cero.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "83bf9151-3bc9-40d2-8615-31570238b08e",
      "metadata": {},
      "source": [
        "<span id=\"optimize\" />\n",
        "\n",
        "<span id=\"step-2-optimize-the-circuits-and-operators\" />\n",
        "\n",
        "### Paso 2. Optimizar los circuitos y los operadores\n",
        "\n",
        "Al ejecutar circuitos en un dispositivo, es importante optimizar el conjunto de instrucciones que contiene el circuito y minimizar la profundidad total (aproximadamente el número de instrucciones) del circuito. Esto garantiza que obtenga los mejores resultados posibles al reducir los efectos del error y el ruido. Además, las instrucciones del circuito deben ajustarse a la [arquitectura del conjunto de instrucciones (ISA)](/docs/guides/transpile#instruction-set-architecture) del dispositivo backend y deben tener en cuenta las puertas básicas y la conectividad de los qubits del dispositivo.\n",
        "\n",
        "El siguiente código instancia un dispositivo real al que enviar un trabajo y transforma el circuito y los observables para que coincidan con la ISA de ese backend. Es necesario que ya haya [guardado sus credenciales.](/docs/guides/cloud-setup)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "9a901271",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/hello-world/extracted-outputs/9a901271-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "service = QiskitRuntimeService()\n",
        "\n",
        "backend = service.least_busy(simulator=False, operational=True)\n",
        "\n",
        "# Convert to an ISA circuit and layout-mapped observables.\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "isa_circuit = pm.run(qc)\n",
        "\n",
        "isa_circuit.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9acac1d4",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute-using-the-quantum-primitives\" />\n",
        "\n",
        "### Paso 3. Ejecutar utilizando las primitivas cuánticas\n",
        "\n",
        "Los ordenadores cuánticos pueden generar resultados aleatorios, por lo que normalmente se recopila una muestra de los resultados ejecutando el circuito varias veces. Puedes calcular el valor de la variable observable utilizando la `Estimator` clase. `Estimator` es una de las dos [funciones primitivas](/docs/guides/get-started-with-estimator); la otra es `Sampler`, que se puede utilizar para obtener datos de un ordenador cuántico.  Estos objetos disponen de un `run()` método que lleva a cabo la selección de circuitos, observables y parámetros (si procede), utilizando un [bloque unificado primitivo ( PUB )](/docs/guides/get-started-with-sampler).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "62c4ca44",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>> Job ID: d9bjj3u6hjac73ffpth0\n"
          ]
        }
      ],
      "source": [
        "# Construct the Estimator instance.\n",
        "\n",
        "estimator = Estimator(mode=backend)\n",
        "estimator.options.resilience_level = 1\n",
        "estimator.options.default_shots = 5000\n",
        "\n",
        "mapped_observables = [\n",
        "    observable.apply_layout(isa_circuit.layout) for observable in observables\n",
        "]\n",
        "\n",
        "# One pub, with one circuit to run against five different observables.\n",
        "job = estimator.run([(isa_circuit, mapped_observables)])\n",
        "\n",
        "# Use the job ID to retrieve your job data later\n",
        "print(f\">>> Job ID: {job.job_id()}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "47479e76",
      "metadata": {},
      "source": [
        "Después de enviar un trabajo, puede esperar hasta que se complete dentro de su instancia actual de Python o utilizar `job_id` para recuperar los datos más tarde.  (Consulte la [sección sobre recuperación de trabajos](/docs/guides/monitor-job#retrieve-job-results-at-a-later-time) para obtener más detalles)\n",
        "\n",
        "Una vez completado el trabajo, examine su resultado a través del atributo `result()` del trabajo.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "792d2f01",
      "metadata": {},
      "outputs": [],
      "source": [
        "# This is the result of the entire submission.  You submitted one Pub,\n",
        "# so this contains one inner result (and some metadata of its own).\n",
        "job_result = job.result()\n",
        "\n",
        "# This is the result from our single pub, which had six observables,\n",
        "# so contains information on all six.\n",
        "pub_result = job.result()[0]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "48317a25",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\" title=\"Alternativa: ejecutar el ejemplo utilizando un simulador\">\n",
        "  Cuando ejecutas tu programa cuántico en un dispositivo real, tu carga de trabajo debe esperar en una cola antes de ejecutarse. Para ahorrar tiempo, puede utilizar el siguiente código para ejecutar esta pequeña carga de trabajo en el [`fake_provider`](../api/qiskit-ibm-runtime/fake-provider) con el modo de Qiskit Runtime prueba local. Tenga en cuenta que esto solo es posible para un circuito pequeño. Cuando amplíes la siguiente sección, necesitarás utilizar un dispositivo real.\n",
        "\n",
        "  ```python\n",
        "\n",
        "  # Use the following code instead if you want to run on a simulator:\n",
        "\n",
        "  from qiskit_ibm_runtime.fake_provider import FakeBelemV2\n",
        "  backend = FakeBelemV2()\n",
        "  estimator = Estimator(backend)\n",
        "\n",
        "  # Convert to an ISA circuit and layout-mapped observables.\n",
        "\n",
        "  pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "  isa_circuit = pm.run(qc)\n",
        "  mapped_observables = [\n",
        "      observable.apply_layout(isa_circuit.layout) for observable in observables\n",
        "  ]\n",
        "\n",
        "  job = estimator.run([(isa_circuit, mapped_observables)])\n",
        "  result = job.result()\n",
        "\n",
        "  # This is the result of the entire submission. You submitted one Pub,\n",
        "  # so this contains one inner result (and some metadata of its own).\n",
        "\n",
        "  job_result = job.result()\n",
        "\n",
        "  # This is the result from our single pub, which had five observables,\n",
        "  # so contains information on all five.\n",
        "\n",
        "  pub_result = job.result()[0]\n",
        "  ```\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d200d1f8",
      "metadata": {},
      "source": [
        "<span id=\"step-4-analyze-the-results\" />\n",
        "\n",
        "### Paso 4. Analizar los resultados\n",
        "\n",
        "El paso de análisis es normalmente donde se pueden procesar los resultados utilizando, por ejemplo, la mitigación del error de medición o la extrapolación de ruido cero (ZNE). Puede introducir estos resultados en otro flujo de trabajo para realizar análisis adicionales o preparar un gráfico con los valores y datos clave. En general, este paso es específico para su problema.  Para este ejemplo, represente gráficamente cada uno de los valores esperados que se midieron para nuestro circuito.\n",
        "\n",
        "Se puede acceder a los valores esperados y a las desviaciones estándar de las magnitudes observables que se han especificado en Estimator a través de los atributos y `PubResult.data.stds` del `PubResult.data.evs` resultado del trabajo. Para obtener los resultados de Sampler, utiliza la `PubResult.data.meas.get_counts()` función, que devolverá un `dict` conjunto de mediciones en forma de cadenas de bits como claves y recuentos como sus valores correspondientes. Para obtener más información, consulta la guía [de inicio rápido de Sampler](/docs/guides/get-started-with-sampler).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "87143fcc",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/hello-world/extracted-outputs/87143fcc-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Plot the result\n",
        "\n",
        "values = pub_result.data.evs\n",
        "\n",
        "errors = pub_result.data.stds\n",
        "\n",
        "# plotting graph\n",
        "plt.plot(observables_labels, values, \"-o\")\n",
        "plt.xlabel(\"Observables\")\n",
        "plt.ylabel(\"Values\")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e6a9ba84",
      "metadata": {},
      "source": [
        "Obsérvese que para los qubits 0 y 1, los valores esperados independientes tanto de X como de Z son 0, mientras que las correlaciones (`XX` y `ZZ`) son 1. Esta es una característica distintiva del entrelazamiento cuántico.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0bc582d8",
      "metadata": {},
      "source": [
        "<span id=\"scale-to-large-numbers-of-qubits\" />\n",
        "\n",
        "## Escalar a un gran número de qubits\n",
        "\n",
        "En la informática cuántica, el trabajo a escala industrial es crucial para avanzar en este campo. Este tipo de trabajo requiere realizar cálculos a una escala mucho mayor, trabajando con circuitos que pueden utilizar más de 100 qubits y más de 1000 puertas. Este ejemplo muestra cómo se puede realizar un trabajo a escala industrial en IBM® QPU creando y analizando un estado GHZ de 100 qubits.  Utiliza el flujo de trabajo de patrones de Qiskit y termina midiendo el valor esperado $\\langle Z_0 Z_i \\rangle $ para cada qubit.\n",
        "\n",
        "<span id=\"step-1-map-the-problem\" />\n",
        "\n",
        "### Paso 1. Identificar el problema\n",
        "\n",
        "Escribe una función que devuelva un `QuantumCircuit` que prepare un $n$ estado GHZ de qubits (esencialmente un estado Bell extendido) y, a continuación, utiliza esa función para preparar un estado GHZ de 100 qubits y recopilar los observables que se van a medir.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "2ac02692",
      "metadata": {},
      "outputs": [],
      "source": [
        "def get_qc_for_n_qubit_GHZ_state(n: int) -> QuantumCircuit:\n",
        "    \"\"\"This function will create a qiskit.QuantumCircuit (qc)\n",
        "        for an n-qubit GHZ state.\n",
        "\n",
        "    Args:\n",
        "        n (int): Number of qubits in the n-qubit GHZ state\n",
        "\n",
        "    Returns:\n",
        "        QuantumCircuit: Quantum circuit that generate the n-qubit GHZ state,\n",
        "            assuming all qubits start in the 0 state\n",
        "    \"\"\"\n",
        "    if isinstance(n, int) and n >= 2:\n",
        "        qc = QuantumCircuit(n)\n",
        "        qc.h(0)\n",
        "        for i in range(n - 1):\n",
        "            qc.cx(i, i + 1)\n",
        "    else:\n",
        "        raise Exception(\"n is not a valid input\")\n",
        "    return qc\n",
        "\n",
        "\n",
        "# Create a new circuit with 100 qubits in the GHZ state\n",
        "n = 100\n",
        "qc = get_qc_for_n_qubit_GHZ_state(n)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5b3d0d74",
      "metadata": {},
      "source": [
        "A continuación, asigne los operadores de interés. Este ejemplo utiliza los `ZZ` operadores entre qubits para examinar el comportamiento a medida que se alejan entre sí.  Los valores de expectativa cada vez más inexactos (corruptos) entre qubits distantes revelarían el nivel de ruido presente.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "863a4ec9",
      "metadata": {},
      "outputs": [],
      "source": [
        "# ZZII...II, ZIZI...II, ... , ZIII...IZ\n",
        "operator_strings = [\n",
        "    \"Z\" + \"I\" * i + \"Z\" + \"I\" * (n - 2 - i) for i in range(n - 1)\n",
        "]\n",
        "\n",
        "operators = [SparsePauliOp(operator) for operator in operator_strings]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a0b462ce",
      "metadata": {},
      "source": [
        "<span id=\"step-2-optimize-the-problem-for-execution-on-quantum-hardware\" />\n",
        "\n",
        "### Paso 2. Optimizar el problema para su ejecución en hardware cuántico\n",
        "\n",
        "El siguiente código transforma el circuito y los observables para que coincidan con la ISA del backend. Es necesario que ya haya [guardado sus credenciales.](/docs/guides/cloud-setup)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "428f05e7",
      "metadata": {},
      "outputs": [],
      "source": [
        "service = QiskitRuntimeService()\n",
        "\n",
        "backend = service.least_busy(\n",
        "    simulator=False, operational=True, min_num_qubits=100\n",
        ")\n",
        "pm = generate_preset_pass_manager(optimization_level=1, backend=backend)\n",
        "\n",
        "isa_circuit = pm.run(qc)\n",
        "isa_operators_list = [op.apply_layout(isa_circuit.layout) for op in operators]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2d2b5065",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute-on-hardware\" />\n",
        "\n",
        "### Paso 3. Ejecutar en hardware\n",
        "\n",
        "Envía el trabajo y activa la supresión de errores utilizando una técnica para reducir los errores denominada «[desacoplamiento dinámico](/docs/api/qiskit-ibm-runtime/options-dynamical-decoupling-options) ». El nivel de resiliencia indica el grado de resiliencia que se debe implementar frente a los errores. Los niveles más altos generan resultados más precisos, aunque a costa de tiempos de procesamiento más largos.  Para obtener más información sobre las opciones configuradas en el siguiente código, consulte «[Configurar la mitigación de errores para Qiskit Runtime](/docs/guides/error-mitigation-and-suppression-techniques) ».\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "3aaa5025",
      "metadata": {},
      "outputs": [],
      "source": [
        "options = EstimatorOptions()\n",
        "options.resilience_level = 1\n",
        "options.dynamical_decoupling.enable = True\n",
        "options.dynamical_decoupling.sequence_type = \"XY4\"\n",
        "\n",
        "# Create an Estimator object\n",
        "estimator = Estimator(backend, options=options)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "b4c3d3e7-0a0f-4023-8948-1082e225f46c",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "d9bk5brv6alc73ct68ag\n"
          ]
        }
      ],
      "source": [
        "# Submit the circuit to Estimator\n",
        "job = estimator.run([(isa_circuit, isa_operators_list)])\n",
        "job_id = job.job_id()\n",
        "print(job_id)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0bc64091",
      "metadata": {},
      "source": [
        "<span id=\"step-4-post-process-results\" />\n",
        "\n",
        "### Paso 4. Resultados del procesamiento posterior\n",
        "\n",
        "Una vez completado el trabajo, represente gráficamente los resultados y observe que $\\langle Z_0 Z_i \\rangle$ disminuye al aumentar $i$, aunque en una simulación ideal todos $\\langle Z_0 Z_i \\rangle$ los deberían ser 1.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "de91ebd0",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/hello-world/extracted-outputs/de91ebd0-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# data\n",
        "data = list(range(1, len(operators) + 1))  # Distance between the Z operators\n",
        "result = job.result()[0]\n",
        "values = result.data.evs  # Expectation value at each Z operator.\n",
        "values = [\n",
        "    v / values[0] for v in values\n",
        "]  # Normalize the expectation values to evaluate how they decay with distance.\n",
        "\n",
        "# plotting graph\n",
        "plt.plot(data, values, marker=\"o\", label=\"100-qubit GHZ state\")\n",
        "plt.xlabel(\"Distance between qubits $i$\")\n",
        "plt.ylabel(r\"$\\langle Z_i Z_0 \\rangle / \\langle Z_1 Z_0 \\rangle $\")\n",
        "plt.legend()\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0afc307c",
      "metadata": {},
      "source": [
        "El gráfico anterior muestra que, a medida que aumenta la distancia entre los qubits, la señal se debilita debido a la presencia de ruido.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e7c24c81",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximos pasos\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendaciones\">\n",
        "  * Prueba uno de estos tutoriales:\n",
        "    * [Estimación de la energía del estado fundamental de la cadena de Heisenberg con VQE](/docs/tutorials/spin-chain-vqe)\n",
        "    * Resuelve problemas de optimización utilizando [QAOA.](/docs/tutorials/quantum-approximate-optimization-algorithm)\n",
        "    * Entrenar modelos [de kernel cuántico](/docs/tutorials/quantum-kernel-training) para tareas de aprendizaje automático\n",
        "  * Encuentre instrucciones detalladas de instalación en la guía [Instalar Qiskit](/docs/guides/install-qiskit).\n",
        "  * Si prefiere no instalar Qiskit localmente, lea sobre las opciones para utilizar Qiskit en un [entorno de desarrollo en línea](/docs/guides/online-lab-environments).\n",
        "  * Para guardar las credenciales de varias cuentas o especificar otras opciones de cuenta, consulte las instrucciones detalladas en la guía [Guardar sus credenciales de inicio de sesión](/docs/guides/save-credentials#save-your-access-credentials).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "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"
    },
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "state": {},
        "version_major": 2,
        "version_minor": 0
      }
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}