{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "4046fd82",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Empieza a utilizar Qiskit en el aula\"\n",
        "description: \"Aprende los conceptos básicos de la computación cuántica y cómo ejecutar tu primer circuito cuántico con Qiskit.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore checkmark ccnot */}\n",
        "\n",
        "<span id=\"get-started-with-qiskit-in-the-classroom\" />\n",
        "\n",
        "# Empieza a utilizar Qiskit en el aula\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a84d2a96-7885-4f6c-b34a-f2d386d4e120",
      "metadata": {},
      "source": [
        "Para este módulo de Qiskit en las aulas, los estudiantes deben tener un entorno Python en funcionamiento con los siguientes paquetes instalados:\n",
        "\n",
        "* `qiskit` v2.1.0 o más reciente\n",
        "* `qiskit-ibm-runtime` v0.40.1 o más reciente\n",
        "* `qiskit-aer` v0.17.0 o más reciente\n",
        "* `qiskit.visualization`\n",
        "* `numpy`\n",
        "* `pylatexenc`\n",
        "\n",
        "Para configurar e instalar los paquetes anteriores, consulta la guía [Instalar Qiskit](/docs/guides/install-qiskit).\n",
        "Para ejecutar trabajos en ordenadores cuánticos reales, los estudiantes deberán crear una cuenta en IBM Quantum® siguiendo los pasos de la guía [Configure su cuenta en IBM Cloud®](/docs/guides/cloud-setup).\n",
        "\n",
        "Este módulo fue probado y utilizó 2 segundos de tiempo QPU en un procesador Heron v2. Esto es sólo una estimación. Su uso real puede variar.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "d611274c-5988-45b7-98bf-01c57edc0b02",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Uncomment and modify this line as needed to install dependencies\n",
        "#!pip install 'qiskit>=2.1.0' 'qiskit-ibm-runtime>=0.40.1' 'qiskit-aer>=0.17.0' 'numpy' 'pylatexenc'"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9a7cc00a-e11d-46e7-9737-1ec7a3fa9951",
      "metadata": {},
      "source": [
        "<span id=\"introduction\" />\n",
        "\n",
        "## Introducción\n",
        "\n",
        "En los módulos de Qiskit en el aula, tendrás la oportunidad de utilizar un ordenador cuántico para explorar diversos conceptos de campos afines a la informática cuántica, como la mecánica cuántica, la informática, la química, etc. Este módulo sirve como prerrequisito para los demás: introduce los fundamentos de la computación cuántica y cómo utilizar Qiskit para ejecutar circuitos cuánticos.\n",
        "\n",
        "Primero le explicaremos brevemente cómo funciona un ordenador clásico y después le mostraremos cómo se adaptan estos conceptos al paradigma de la computación cuántica. Por último, te mostraremos cómo unir estos conceptos para construir y ejecutar tu primer circuito cuántico.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "742678ad-9e14-4691-bc6f-5900c7f45f9b",
      "metadata": {},
      "source": [
        "<span id=\"classical-computers\" />\n",
        "\n",
        "## Ordenadores clásicos\n",
        "\n",
        "Es probable que conozca los fundamentos del funcionamiento de los ordenadores clásicos, pero aquí destacaremos algunas de las características clave para poder establecer una comparación con los ordenadores cuánticos.\n",
        "\n",
        "<span id=\"the-basic-units-of-information-bits\" />\n",
        "\n",
        "### Las unidades básicas de información: bits\n",
        "\n",
        "Los ordenadores clásicos procesan información clásica, y la unidad fundamental de la información clásica es el *bit*. Un solo bit puede almacenar la respuesta a una pregunta \"sí/no\". Solemos representar los dos estados binarios de un bit como \"0\" y \"1\".\n",
        "\n",
        "<span id=\"review-of-binary-numbers\" />\n",
        "\n",
        "#### Revisión de números binarios\n",
        "\n",
        "Combinar bits permite almacenar más información. Por ejemplo, si quieres almacenar un número del 0 al 15, podrías hacerlo con cuatro bits de la siguiente manera:\n",
        "\n",
        "|          |          |           |           |\n",
        "| :------- | :------: | :-------: | --------: |\n",
        "| 0 = 0000 | 4 = 0100 |  8 = 1000 | 12 = 1100 |\n",
        "| 1 = 0001 | 5 = 0101 |  9 = 1001 | 13 = 1101 |\n",
        "| 2 = 0010 | 6 = 0110 | 10 = 1010 | 14 = 1110 |\n",
        "| 3 = 0011 | 7 = 0111 | 11 = 1011 | 15 = 1111 |\n",
        "\n",
        "En general, para pasar de un número binario de $N$ bits a un número familiar, base-10, se multiplica el bit menos significativo (más a la derecha) por $2^0 = 1$, el siguiente bit a la izquierda por $2^1 = 2$, luego el siguiente por $2^2 = 4$, y así sucesivamente, hasta llegar al más significativo (bit más a la izquierda), que se multiplica $2^{N-1}$.\n",
        "\n",
        "Esto significa que $N$ bits pueden estar en uno de los $2^N$ estados posibles.\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Comprueba tu comprensión\n",
        "\n",
        "¿Cuántos bits necesitarías para representar el número 86? Escribe la cadena de bits que codifica este número en binario.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Respuesta\">\n",
        "    Recuerde que $N$ bits le permite representar los números $0$ a $2^N - 1$, por lo que utilizando seis bits llegaríamos hasta $2^6 - 1 = 63$. Eso no es suficiente. Añadimos un bit más para llegar a $2^7 - 1 = 127$. Ahora descompongamos 86 en potencias de 2:\n",
        "\n",
        "    $$\n",
        "    \\begin{aligned}\n",
        "    86 &= 64 + 16 + 4 + 2 \\\\\n",
        "    &= 2^6 \\times 1 + 2^5 \\times 0 + 2^4 \\times 1 + 2^3 \\times 0 + 2^2 \\times 1 + 2^1 \\times 1 + 2^0 \\times 0 \\\\\n",
        "    &= 1010110\n",
        "    \\end{aligned}\n",
        "    $$\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "<span id=\"fundamental-operations-gates\" />\n",
        "\n",
        "### Operaciones fundamentales: puertas\n",
        "\n",
        "Ahora bien, un ordenador necesita poder *hacer* algo con los bits para, bueno, computar. Las puertas binarias son las operaciones que forman los bloques de construcción fundamentales de todos los algoritmos y códigos más complicados.\n",
        "\n",
        "<span id=\"single-bit-gate\" />\n",
        "\n",
        "### Puerta de un solo bit:\n",
        "\n",
        "<span id=\"not\" />\n",
        "\n",
        "#### NO\n",
        "\n",
        "Cuando sólo tienes un bit, sólo hay una forma de transformar su estado: cambiar el estado de 0 a 1 o de 1 a 0. A esto lo llamamos la puerta \"NO\". El efecto de esta puerta -y del resto de puertas que veremos a continuación- puede representarse en una \"tabla de verdad\", con columnas para los estados de entrada y salida de los qubits. La tabla de verdad de la puerta NOT es:\n",
        "\n",
        "| Entrada | Resultado |\n",
        "| :------ | --------: |\n",
        "| 0       |         1 |\n",
        "| 1       |         0 |\n",
        "\n",
        "<span id=\"multi-bit-gates\" />\n",
        "\n",
        "### Puertas multibit:\n",
        "\n",
        "<span id=\"and\" />\n",
        "\n",
        "#### Y\n",
        "\n",
        "AND es una puerta de dos bits que toma dos bits de entrada y emite un único bit. La salida es 1 si los dos bits de entrada son 1 y 0 en caso contrario:\n",
        "\n",
        "| Entrada | Resultado |\n",
        "| :------ | --------: |\n",
        "| 00      |         0 |\n",
        "| 01      |         0 |\n",
        "| 10      |         0 |\n",
        "| 5       |         1 |\n",
        "\n",
        "<span id=\"or\" />\n",
        "\n",
        "#### O\n",
        "\n",
        "OR es otra puerta de dos bits con un único bit de salida. Sale 1 si *cualquiera de* los bits es 1:\n",
        "\n",
        "| Entrada | Resultado |\n",
        "| :------ | --------: |\n",
        "| 00      |         0 |\n",
        "| 01      |         1 |\n",
        "| 10      |         1 |\n",
        "| 5       |         1 |\n",
        "\n",
        "<span id=\"xor\" />\n",
        "\n",
        "#### XO\n",
        "\n",
        "XOR significa \"OR exclusivo\" y es como la puerta OR, pero da como resultado 1 si *sólo uno* de los bits de entrada es 1. La salida es 0 si ambos son 1 o ambos son 0:\n",
        "\n",
        "| Entrada | Resultado |\n",
        "| :------ | --------: |\n",
        "| 00      |         0 |\n",
        "| 01      |         1 |\n",
        "| 10      |         1 |\n",
        "| 5       |         0 |\n",
        "\n",
        "<span id=\"measurements\" />\n",
        "\n",
        "### Medidas:\n",
        "\n",
        "Normalmente, cuando se aprende informática clásica, no se presta mucha atención al proceso de lectura del estado de los bits. Esto se debe a que no es muy complejo desde una perspectiva conceptual. Puedes medir los bits en cualquier momento antes, durante o después de un cálculo, y no afecta al resultado. Este no es el caso de la computación cuántica, como veremos a continuación.\n",
        "\n",
        "<span id=\"circuits\" />\n",
        "\n",
        "### Circuitos:\n",
        "\n",
        "Combinando las puertas anteriores, puedes hacer cualquier tipo de operación que quieras en un ordenador. Veamos un ejemplo sencillo: Utilizando las puertas AND y XOR, puedes construir el circuito de media escalera, que calcula la suma de dos bits. Esto se representa en un diagrama de circuito lógico, donde los hilos representan los bits y las puertas que operan sobre los bits se muestran como símbolos en los hilos correspondientes:\n",
        "\n",
        "![Esquema clásico del circuito de media escalera. Una puerta XOR genera el bit de salida Sum y una puerta AND genera el bit de salida Carry.](https://quantum.cloud.ibm.com/learning/images/modules/quantum-mechanics/get-started-with-qiskit/classicaladder.avif)\n",
        "\n",
        "Así, los dos bits se copian y pasan por una puerta AND y una puerta XOR. El resultado de la puerta XOR es el \"bit de suma\" (S), que permanece en el lugar de los unos del número binario, y el resultado de la puerta AND es el \"bit de acarreo\" (C), que es el valor del siguiente dígito más significativo del número binario. Aquí está la tabla de verdad:\n",
        "\n",
        "| $A$ | $B$ | Suma ( $A \\oplus B$ ) | Carry ( $A \\wedge B$ ) |\n",
        "| --- | --- | --------------------- | ---------------------- |\n",
        "| 0   | 0   | 0                     | 0                      |\n",
        "| 0   | 1   | 1                     | 0                      |\n",
        "| 1   | 0   | 1                     | 0                      |\n",
        "| 1   | 1   | 0                     | 1                      |\n",
        "\n",
        "<span id=\"check-your-understanding-1\" />\n",
        "\n",
        "#### Comprueba tu comprensión\n",
        "\n",
        "Comprueba que la tabla de verdad anterior da la solución correcta para un circuito sumador. Es decir, para cada una de las cuatro opciones de A y B, verifica que $A+B=S+2 \\times C$.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Respuesta\">\n",
        "    $$\n",
        "    \\begin{aligned}\n",
        "    0+0 &= 0+0 = 0 ~\\checkmark \\\\\n",
        "    0+1 &= 1+0 = 1  ~\\checkmark \\\\\n",
        "    1+0 &= 1+0 = 1  ~\\checkmark \\\\\n",
        "    1+1 &= 0+2 = 2 ~\\checkmark \\\\\n",
        "    \\end{aligned}\n",
        "    $$\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a324a959-5edc-4aaf-91ad-6bef9ab7c435",
      "metadata": {},
      "source": [
        "<span id=\"quantum-computers\" />\n",
        "\n",
        "## Ordenadores cuánticos\n",
        "\n",
        "<span id=\"bits-$rightarrow$-qubits\" />\n",
        "\n",
        "### Bits $\\rightarrow$ qubits\n",
        "\n",
        "Al igual que los bits son las unidades fundamentales de la información clásica, los bits *cuánticos*, o \"qubits\", son las unidades fundamentales de la información cuántica. Al igual que el bit clásico, el estado de un qubit puede ser 0 o 1, que normalmente denotamos como $\\vert 0\\rangle$ y $\\vert 1\\rangle$. Pero a diferencia del bit clásico, un bit cuántico también puede estar en una *superposición* de los estados $\\vert 0\\rangle$ y $\\vert 1\\rangle$ al mismo tiempo. En general, un qubit puede estar en cualquier estado $\\vert \\psi\\rangle$ de la forma:\n",
        "\n",
        "$$\n",
        "\\vert \\psi\\rangle = c_0 \\vert 0\\rangle + c_1 \\vert 1\\rangle\n",
        "$$\n",
        "\n",
        "donde $c_0$ y $c_1$ son amplitudes complejas con $\\vert c_0 \\vert ^2+\\vert c_1\\vert ^2=1$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "11563bfb-93d4-4a6a-9bd9-b52665ab4517",
      "metadata": {},
      "source": [
        "<span id=\"the-quantum-phase\" />\n",
        "\n",
        "#### La fase cuántica\n",
        "\n",
        "Dado que $c_0$ y $c_1$ son complejos, cada uno de ellos puede escribirse como $c_i = \\vert c_i\\vert e^{i\\phi_i}$, donde $\\phi_i$ se denomina *fase*. Si multiplicamos todo el estado por el mismo factor de fase global, nada cambia físicamente: es lo que se denomina fase global, y no tiene consecuencias observables.\n",
        "\n",
        "Por esta razón, es convencional \"factorizar\" $e^{i\\phi_0}$, dando:\n",
        "\n",
        "$\\vert \\psi\\rangle = \\vert c_0\\vert \\vert 0\\rangle + \\vert c_1\\vert e^{i\\phi}\\vert 1\\rangle$\n",
        "\n",
        "donde $\\phi = \\phi_1-\\phi_0$ es la fase *relativa* del estado cuántico, que *sí* tiene consecuencias observables.\n",
        "\n",
        "Esta fase desempeña un papel muy importante en la computación cuántica, y explorarás sus diversas consecuencias en los siguientes módulos de Qiskit en el Aula.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c35a8265-2d19-4743-99ac-39192e46f59a",
      "metadata": {},
      "source": [
        "<span id=\"multiple-qubits\" />\n",
        "\n",
        "#### Múltiples qubits\n",
        "\n",
        "Mientras que el estado de múltiples bits podría expresarse simplemente como una cadena de 0s y 1s, el estado de múltiples qubits se complica un poco más debido a los principios de *superposición* y *entrelazamiento*.\n",
        "\n",
        "Recordemos que los bits de $N$ pueden estar en uno de los $2^N$ posibles estados que van desde los números binarios 000...000 a 111...111. Pero ahora, gracias al principio de superposición, *los qubits* de $N$ pueden estar en superposición de *todos* estos estados a la vez\n",
        "\n",
        "Esto puede expresarse como\n",
        "\n",
        "$$\n",
        "\\psi_N = \\sum_{i=0}^{2^N-1} c_i \\vert i\\rangle\n",
        "$$\n",
        "\n",
        "donde, como en el caso clásico, el estado $\\vert i\\rangle$ corresponde al estado en el que cada qubit se encuentra en la combinación correcta de 0s y 1s para producir el número binario $i$. Son los llamados \"estados base computacionales\" del sistema cuántico. Por ejemplo, un estado de tres qubits puede escribirse como una superposición de sus ocho estados base computacionales:\n",
        "\n",
        "$$\n",
        "\\psi_3 = c_0 \\vert 000\\rangle + c_1 \\vert 001\\rangle + c_2 \\vert 010\\rangle + c_3 \\vert 011\\rangle + c_4 \\vert 100\\rangle + c_5 \\vert 101\\rangle + c_6 \\vert 110\\rangle + c_7 \\vert 111\\rangle\n",
        "$$\n",
        "\n",
        "Cada qubit del sistema se denota con un índice que va de $0$ a $N-1$. La convención es leer los estados de los qubits de derecha a izquierda, de modo que el estado del qubit $0$ es el más a la derecha y el estado del qubit $N-1$ es el más a la izquierda. Esto se conoce como notación \"little-endian\", y puede parecer contraintuitivo al principio, ya que estamos acostumbrados a leer de izquierda a derecha.\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Comprueba tu comprensión\n",
        "\n",
        "A primera vista, puede parecer contradictorio ordenar los qubits de derecha a izquierda, como en la notación little-endian, pero en realidad es algo muy lógico Explique por qué. (Recuerde nuestra discusión anterior sobre la conversión de números binarios a base-10 )\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Respuesta\">\n",
        "    Si ordenamos los qubits de derecha a izquierda, de forma que el qubit 0 sea el más a la derecha y el qubit N-1 el más a la izquierda, es lógico asociar el qubit $0$ con el bit menos significativo, que se multiplica por $2^0$ y el qubit $N-1$ con el bit más significativo, que se multiplica por $2^{N-1}$.\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "<span id=\"entanglement\" />\n",
        "\n",
        "#### Entrelazamiento\n",
        "\n",
        "Como ya hemos dicho, otra característica clave de los qubits es que pueden *entrelazarse* entre sí. Tomemos un ejemplo de un estado de dos qubits, donde $c_0 = c_3 = \\frac{1}{\\sqrt{2}}$ y $c_1 = c_2 = 0$ :\n",
        "\n",
        "$\\vert \\psi\\rangle = \\frac{1}{\\sqrt{2}}(\\vert 00\\rangle + \\vert 11\\rangle)$\n",
        "\n",
        "Así, el estado del qubit 0 puede ser $\\vert 0\\rangle$ o $\\vert 1\\rangle$ con igual probabilidad, y lo mismo con el estado del qubit 1. Pero estas probabilidades ya no son independientes entre sí. Si encontramos que el estado del qubit 0 es $\\vert 0\\rangle$, entonces *sabemos* que el qubit 1 también estará en $\\vert 0\\rangle$. Esto es cierto sin importar la distancia entre uno y otro, por lo que el acto de medir un estado enredado se denomina a veces \"espeluznante acción a distancia\"\n",
        "\n",
        "El enredo también puede adoptar otras formas. Por ejemplo, el Estado\n",
        "\n",
        "$\\vert \\psi\\rangle = \\frac{1}{\\sqrt{2}}(\\vert 01\\rangle + \\vert 10\\rangle)$\n",
        "\n",
        "produce resultados opuestos cada vez: si se mide un qubit $\\vert 0\\rangle$, se garantiza que el otro se encuentra en el estado $\\vert 1\\rangle$.\n",
        "\n",
        "<span id=\"check-your-understanding-1\" />\n",
        "\n",
        "#### Comprueba tu comprensión\n",
        "\n",
        "¿Está el estado $\\vert \\psi\\rangle = \\vert 11\\rangle$ enredado? ¿Por qué sí o por qué no?\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Respuesta\">\n",
        "    No está enredado. Aunque los resultados son siempre los mismos cuando se miden ambos qubits, esto se debe únicamente a que cada qubit está siempre fijo en el estado $\\vert 1\\rangle$. En realidad, el resultado de la medición de un qubit no depende del otro, sino que ambos están siempre en $\\vert 1\\rangle$.\n",
        "\n",
        "    En general, si se puede describir el estado de cada qubit por separado y luego multiplicarlos juntos así:\n",
        "\n",
        "    $\\vert \\psi\\rangle = \\vert \\psi_1\\rangle \\vert \\psi_0\\rangle $\n",
        "\n",
        "    Entonces se conoce como \"estado producto\" y *no* está enredado.\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "<span id=\"vector-notation\" />\n",
        "\n",
        "#### Notación vectorial\n",
        "\n",
        "A menudo resulta útil utilizar vectores y matrices para ver cómo se transforma el estado cuántico bajo diferentes operaciones. En esta representación, nuestros estados cuánticos serán vectores, y nuestras puertas cuánticas (de las que hablaremos en la siguiente sección) serán matrices que transforman los vectores.\n",
        "\n",
        "Para un único qubit, se elige la forma vectorial de los estados: $\\vert 0\\rangle = \\begin{pmatrix}1 \\\\ 0\\end{pmatrix}$ $\\vert 1\\rangle = \\begin{pmatrix}0 \\\\ 1\\end{pmatrix}$ De este modo, un estado arbitrario $\\vert \\psi\\rangle = a\\vert 0\\rangle+b\\vert 1\\rangle$ puede escribirse como $\\vert \\psi\\rangle =\\begin{pmatrix}a \\\\ b\\end{pmatrix}$\n",
        "\n",
        "Para un estado general, $n$ -qubit, necesitaremos un vector $2^n$ -dimensional, con estados base ordenados como es de esperar, en valor binario ascendente:\n",
        "\n",
        "$$\n",
        "\\vert 0 \\dots 000\\rangle = \\begin{pmatrix}1 \\\\ 0 \\\\ 0 \\\\ \\vdots \\\\ 0\\end{pmatrix}, \\vert 0 \\dots 001 \\rangle = \\vert 1 \\dots 110\\rangle = \\begin{pmatrix}0 \\\\ \\vdots \\\\ 0 \\\\ 1 \\\\ 0\\end{pmatrix}, \\vert 1 \\dots 111 \\rangle = \\begin{pmatrix}0 \\\\ \\vdots \\\\ 0 \\\\ 0\\\\ 1\\end{pmatrix}\n",
        "$$\n",
        "\n",
        "Con esta elección de notación vectorial en mente, podemos introducir nuestras puertas cuánticas necesarias, sus efectos sobre los estados cuánticos y sus formas matriciales.\n",
        "\n",
        "<span id=\"check-your-understanding-2\" />\n",
        "\n",
        "#### Comprueba tu comprensión\n",
        "\n",
        "Existen cuatro estados base computacionales para un sistema de dos qubits. Escribe cada una de ellas en notaciones ket y vectoriales.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Respuesta\">\n",
        "    $$\n",
        "    \\vert 00\\rangle = \\begin{pmatrix}1 \\\\ 0 \\\\ 0 \\\\ 0\\end{pmatrix}, \\vert 01 \\rangle = \\begin{pmatrix}0 \\\\ 1 \\\\ 0 \\\\ 0\\end{pmatrix}, \\dots, \\vert 10\\rangle = \\begin{pmatrix}0 \\\\ 0 \\\\ 1 \\\\ 0\\end{pmatrix}, \\vert 11 \\rangle = \\begin{pmatrix}0 \\\\ 0 \\\\ 0\\\\ 1\\end{pmatrix}\n",
        "    $$\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "52f971a7-4a5e-4571-927b-23a642fae997",
      "metadata": {},
      "source": [
        "<span id=\"gates-$rightarrow$-quantum-gates\" />\n",
        "\n",
        "## Puertas cuánticas « $\\rightarrow$ »\n",
        "\n",
        "Al igual que las puertas clásicas como NOT, AND, OR y XOR pueden combinarse para construir circuitos clásicos arbitrarios, las puertas cuánticas desempeñan el mismo papel en la computación cuántica. Como los qubits tienen características mecánicas cuánticas adicionales, las puertas cuánticas son correspondientemente más ricas. Aunque todavía podemos describir su acción sobre la base de los estados $|0\\rangle$ y $|1\\rangle$ con una tabla de verdad, esto no captura toda la imagen. Para las puertas cuánticas, suele ser más natural utilizar una representación matricial, ya que también actúan sobre superposiciones de estados base.\n",
        "\n",
        "A continuación presentaremos las puertas cuánticas más comunes y cómo transforman los qubits con los que interactúan. Cuando proceda, las relacionaremos con las puertas clásicas conocidas.\n",
        "\n",
        "<span id=\"single-qubit-gates\" />\n",
        "\n",
        "### Puertas de un solo qubit\n",
        "\n",
        "**$X$ puerta** : Es el equivalente cuántico de una operación NOT. Su tabla de verdad es idéntica a la de la puerta NOT clásica:\n",
        "\n",
        "| Entrada          |        Resultado |\n",
        "| :--------------- | ---------------: |\n",
        "| $\\vert 0\\rangle$ | $\\vert 1\\rangle$ |\n",
        "| $\\vert 1\\rangle$ | $\\vert 0\\rangle$ |\n",
        "\n",
        "Y la representación matricial:\n",
        "\n",
        "$X=\\begin{pmatrix} 0 & 1 \\\\ 1 & 0 \\end{pmatrix}$\n",
        "\n",
        "En Qiskit, crear un circuito con una puerta $X$ tiene este aspecto:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "6c215e46-26cb-4e10-a1d7-2eecd2c18294",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/6c215e46-26cb-4e10-a1d7-2eecd2c18294-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "\n",
        "qc = QuantumCircuit(1)\n",
        "qc.x(0)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3a59abe3-5e75-4ff1-9f5e-9b24fd5c5ea0",
      "metadata": {},
      "source": [
        "En este diagrama de circuito tan sencillo, el qubit está representado por un cable, la línea horizontal negra, y la puerta aparece como un recuadro en ese cable.\n",
        "\n",
        "**Puerta de Hadamard:** Crea un estado de superposición. Tabla de verdad:\n",
        "\n",
        "| Entrada          |                                                      Resultado |\n",
        "| :--------------- | -------------------------------------------------------------: |\n",
        "| $\\vert 0\\rangle$ | $\\frac{1}{\\sqrt{2}}\\left(\\vert 0\\rangle+\\vert 1\\rangle\\right)$ |\n",
        "| $\\vert 1\\rangle$ | $\\frac{1}{\\sqrt{2}}\\left(\\vert 0\\rangle-\\vert 1\\rangle\\right)$ |\n",
        "\n",
        "Representación matricial: $H=\\frac{1}{\\sqrt{2}}\\begin{pmatrix} 1 & 1 \\\\ 1 & -1 \\end{pmatrix}$\n",
        "\n",
        "Un circuito con una puerta Hadamard se realiza de la siguiente manera:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "1a009015-4ced-47e4-a18d-d0685e4cab47",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/1a009015-4ced-47e4-a18d-d0685e4cab47-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "\n",
        "qc = QuantumCircuit(1)\n",
        "qc.h(0)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9de7658f-e456-4788-81bb-6900c12ef054",
      "metadata": {},
      "source": [
        "**$Z$ puerta** : Añade un desfase de $\\Delta \\phi = \\pi$ al estado $|1\\rangle$ :\n",
        "\n",
        "| Entrada          |         Resultado |\n",
        "| :--------------- | ----------------: |\n",
        "| $\\vert 0\\rangle$ |  $\\vert 0\\rangle$ |\n",
        "| $\\vert 1\\rangle$ | $-\\vert 1\\rangle$ |\n",
        "\n",
        "$Z=\\begin{pmatrix} 1 & 0 \\\\ 0 & -1 \\end{pmatrix}$\n",
        "\n",
        "En Qiskit, crear un circuito con una puerta $Z$ tiene este aspecto:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "7bca3c98-884b-4709-bbe8-a9e16cc45698",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/7bca3c98-884b-4709-bbe8-a9e16cc45698-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(1)\n",
        "qc.z(0)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c9ee10a5-5f69-4db4-87e9-bc1d3cd051eb",
      "metadata": {},
      "source": [
        "**$T$ puerta** : Añade un desfase de $\\Delta \\phi = \\pi/4$ al estado $|1\\rangle$ :\n",
        "\n",
        "| Entrada          |                  Resultado |\n",
        "| :--------------- | -------------------------: |\n",
        "| $\\vert 0\\rangle$ |           $\\vert 0\\rangle$ |\n",
        "| $\\vert 1\\rangle$ | $e^{i\\pi/4}\\vert 1\\rangle$ |\n",
        "\n",
        "$T=\\begin{pmatrix} 1 & 0 \\\\ 0 & e^{i\\pi/4} \\end{pmatrix}$\n",
        "\n",
        "En Qiskit, crear un circuito con una puerta $T$ tiene este aspecto:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "ac699059-6be5-4a1a-89cb-97b7af412ab8",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/ac699059-6be5-4a1a-89cb-97b7af412ab8-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(1)\n",
        "qc.t(0)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "52b43ac8-be21-4652-a139-7093fe27fd69",
      "metadata": {},
      "source": [
        "<span id=\"multi-qubit-gates\" />\n",
        "\n",
        "### Puertas multi-qubit\n",
        "\n",
        "Las puertas de dos qubits pueden parecerse a las puertas clásicas de dos bits, pero con una salvedad importante: todas las puertas cuánticas deben ser reversibles. En términos de álgebra lineal, esto significa que se representan mediante matrices unitarias. Así, dos qubits de entrada siempre se corresponden con dos qubits de salida, y la operación puede, en principio, deshacerse. Esto contrasta con las puertas clásicas que hemos visto antes, como AND u OR, que pierden información y son irreversibles: dada una salida, no se puede determinar de forma única la entrada.\n",
        "\n",
        "**Puerta CNOT (Controlled-NOT):** Los dos qubits de entrada se denominan qubits \"control\" y \"objetivo\". El qubit de control permanece inalterado, pero su estado dicta lo que ocurre con el qubit objetivo. Si el qubit de control está en el estado $\\vert 1\\rangle$, entonces se aplica una puerta $X$ a ese objetivo; si el estado del qubit de control es $\\vert 0\\rangle$, entonces no se realiza ningún cambio. En la notación siguiente, supongamos que el qubit $A$ (el qubit situado más a la derecha) es el control, y el qubit $B$ (el qubit situado más a la izquierda) es el objetivo. A continuación, la notación utilizada es $CNOT(q_{control},q_{target})\\vert BA\\rangle.$\n",
        "\n",
        "$CNOT(A,B)\\vert BA\\rangle_{input} = \\vert BA\\rangle_{output}$\n",
        "\n",
        "| Entrada           |         Resultado |\n",
        "| :---------------- | ----------------: |\n",
        "| $\\vert 00\\rangle$ | $\\vert 00\\rangle$ |\n",
        "| $\\vert 01\\rangle$ | $\\vert 11\\rangle$ |\n",
        "| $\\vert 10\\rangle$ | $\\vert 10\\rangle$ |\n",
        "| $\\vert 11\\rangle$ | $\\vert 01\\rangle$ |\n",
        "\n",
        "Así, la matriz que representa esta acción es:\n",
        "\n",
        "$CNOT=\\begin{pmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & 1 \\\\ 0 & 0 & 1 & 0 \\\\ 0 & 1 & 0 & 0\\end{pmatrix}$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "1c4dc48d-3d2b-4b4b-b405-c93504815ba9",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/1c4dc48d-3d2b-4b4b-b405-c93504815ba9-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(2)\n",
        "qc.cx(0, 1)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "be45af7b-a148-4b46-8379-3ac9658f50a9",
      "metadata": {},
      "source": [
        "Este es el primer diagrama de circuito que vemos con dos qubits, que están representados por los dos cables. La puerta CNOT se implementa entre los dos qubits, con $q_0$ como control y $q_1$ como objetivo.\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Comprueba tu comprensión\n",
        "\n",
        "La mayoría de las puertas tienen la misma forma de matriz en Qiskit que en cualquier otro sitio. Pero la puerta CNOT actúa sobre dos qubits, por lo que de repente las convenciones de ordenación de los qubits se convierten en un problema. Los textos que ordenan qubits $\\vert q_0,q_1,...\\rangle$ mostrarán una forma de matriz diferente para sus puertas CNOT. Verificar por multiplicación explícita de matrices que la matriz CNOT anterior tiene la acción correcta sobre el estado $\\vert 01\\rangle.$\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Respuesta\">\n",
        "    $CNOT\\vert 01\\rangle =\\begin{pmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & 1 \\\\ 0 & 0 & 1 & 0 \\\\ 0 & 1 & 0 & 0\\end{pmatrix}\\begin{pmatrix}0 \\\\ 1 \\\\ 0 \\\\0\\end{pmatrix} = \\begin{pmatrix}0 \\\\ 0 \\\\ 0 \\\\1\\end{pmatrix} = \\vert 11\\rangle$\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "**Puerta SWAP:** Esta puerta intercambia los estados de dos qubits. Tabla de verdad:\n",
        "\n",
        "| Entrada           |         Resultado |\n",
        "| :---------------- | ----------------: |\n",
        "| $\\vert 00\\rangle$ | $\\vert 00\\rangle$ |\n",
        "| $\\vert 01\\rangle$ | $\\vert 10\\rangle$ |\n",
        "| $\\vert 10\\rangle$ | $\\vert 01\\rangle$ |\n",
        "| $\\vert 11\\rangle$ | $\\vert 11\\rangle$ |\n",
        "\n",
        "Así, la matriz que representa esta acción es:\n",
        "\n",
        "$SWAP=\\begin{pmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 0 & 1 & 0 \\\\ 0 & 1 & 0 & 0 \\\\ 0 & 0 & 0 & 1\\end{pmatrix}$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "118da691-4208-4248-a21f-a5e22815dc2c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/118da691-4208-4248-a21f-a5e22815dc2c-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(2)\n",
        "qc.swap(0, 1)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "78199ae4-93e4-49a2-948a-f41a22187bae",
      "metadata": {},
      "source": [
        "En realidad, la puerta SWAP puede construirse a partir de tres CNOT. Para ver cómo, podemos `decompose()` la puerta con Qiskit:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "5efa09b9-b3e4-43fb-81f3-c33283a992d2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/5efa09b9-b3e4-43fb-81f3-c33283a992d2-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(2)\n",
        "qc.swap(0, 1)\n",
        "qc.decompose().draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "330362e5-f040-426f-a6d9-d730c917c7f2",
      "metadata": {},
      "source": [
        "Aquí vemos por primera vez cómo se muestran múltiples puertas en un diagrama de circuito. Lo leemos de izquierda a derecha, por lo que la puerta situada más a la izquierda se aplica primero.\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Comprueba tu comprensión\n",
        "\n",
        "Compruebe que la combinación de CNOTs anterior da como resultado una puerta SWAP. Puedes hacerlo con la multiplicación de matrices o con cualquier otro método.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Respuesta\">\n",
        "    Con multiplicación de matrices:\n",
        "\n",
        "    $\\begin{pmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & 1 \\\\ 0 & 0 & 1 & 0 \\\\ 0 & 1 & 0 & 0\\end{pmatrix} \\begin{pmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 1 & 0 & 0 \\\\ 0 & 0 & 0 & 1 \\\\ 0 & 0 & 1 & 0\\end{pmatrix} \\begin{pmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & 1 \\\\ 0 & 0 & 1 & 0 \\\\ 0 & 1 & 0 & 0\\end{pmatrix} = \\begin{pmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 0 & 1 & 0 \\\\ 0 & 1 & 0 & 0 \\\\ 0 & 0 & 0 & 1\\end{pmatrix} = SWAP ~\\checkmark$\n",
        "\n",
        "    Utilizar una tabla de verdad para ver cómo cambian los estados con cada CNOT. En la última columna, los estados deben ser equivalentes a la columna \"salida\" de la tabla verdadero-falso SWAP:\n",
        "\n",
        "    | Entrada           |     CNOT(A,B)     |     CNOT(B,A)     |                    CNOT(A,B) |\n",
        "    | :---------------- | :---------------: | :---------------: | ---------------------------: |\n",
        "    | $\\vert 00\\rangle$ | $\\vert 00\\rangle$ | $\\vert 00\\rangle$ | $\\vert 00\\rangle \\checkmark$ |\n",
        "    | $\\vert 01\\rangle$ | $\\vert 11\\rangle$ | $\\vert 10\\rangle$ | $\\vert 10\\rangle \\checkmark$ |\n",
        "    | $\\vert 10\\rangle$ | $\\vert 10\\rangle$ | $\\vert 11\\rangle$ | $\\vert 01\\rangle \\checkmark$ |\n",
        "    | $\\vert 11\\rangle$ | $\\vert 01\\rangle$ | $\\vert 01\\rangle$ | $\\vert 11\\rangle \\checkmark$ |\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "**Puerta de Toffoli (o \"controlada-controlada-NOT\" (CCNOT)):** Se trata de una puerta *de tres qubits*. Puede que el nombre \"controlado-controlado-NOT\" ya le indique cómo funciona: hay dos qubits de control y un qubit objetivo, y el estado del qubit objetivo se invierte sólo si *ambos* qubits de control están en el estado $\\vert 1\\rangle$. Mantenemos la convención de ordenación que utilizamos con el CNOT:\n",
        "\n",
        "$$\n",
        "CCNOT(Control A, Control B, Target C)\\vert CBA\\rangle\n",
        "$$\n",
        "\n",
        "Así que la tabla de verdad es:\n",
        "\n",
        "| Entrada            |          Resultado |\n",
        "| :----------------- | -----------------: |\n",
        "| $\\vert 000\\rangle$ | $\\vert 000\\rangle$ |\n",
        "| $\\vert 001\\rangle$ | $\\vert 001\\rangle$ |\n",
        "| $\\vert 010\\rangle$ | $\\vert 010\\rangle$ |\n",
        "| $\\vert 011\\rangle$ | $\\vert 111\\rangle$ |\n",
        "| $\\vert 100\\rangle$ | $\\vert 100\\rangle$ |\n",
        "| $\\vert 101\\rangle$ | $\\vert 101\\rangle$ |\n",
        "| $\\vert 110\\rangle$ | $\\vert 110\\rangle$ |\n",
        "| $\\vert 111\\rangle$ | $\\vert 011\\rangle$ |\n",
        "\n",
        "Y la matriz que representa esta acción es:\n",
        "\n",
        "$$\n",
        "CCNOT=\\begin{pmatrix} 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\0 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\\\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\\\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\\\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0\\end{pmatrix}\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "d1829257-b7a4-49d9-8ac2-3d6230165427",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/d1829257-b7a4-49d9-8ac2-3d6230165427-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(3)\n",
        "qc.ccx(0, 1, 2)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "aa2e83e5-1197-473c-9f16-4c264b08aca0",
      "metadata": {},
      "source": [
        "La puerta de Toffoli también puede descomponerse en CNOT, junto con otras puertas. Sin embargo, es significativamente más complicada que la descomposición de la puerta SWAP, por lo que se dejará como ejercicio opcional al final del módulo explorar y verificar esta descomposición.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "970302ee-eccc-48eb-b255-4a2d7bc8fbbc",
      "metadata": {},
      "source": [
        "<span id=\"measurements\" />\n",
        "\n",
        "## Mediciones\n",
        "\n",
        "Las mediciones desempeñan un papel especial en la computación cuántica, que no tiene análogo en la computación clásica. Mientras que en la computación clásica se pueden comprobar los bits en cualquier momento del algoritmo, en la computación cuántica hay que ser muy selectivo a la hora de mirar los qubits, ya que la medición colapsa su estado y destruye la superposición que confiere a los qubits su complejidad computacional.\n",
        "\n",
        "En particular, dado un estado cuántico de $N$ -bit $\\vert \\psi\\rangle = \\sum_{i=0}^{2^N-1} c_i \\vert i\\rangle$, una medición colapsará el estado a una de las funciones base $\\vert i\\rangle$ con una probabilidad igual a $\\vert c_i\\vert ^2$.\n",
        "\n",
        "Pero este efecto destructivo de una medida no siempre es un obstáculo. De hecho, es un recurso clave en determinados algoritmos y protocolos, como [la teletransportación cuántica](/learning/modules/computer-science/quantum-teleportation) y la [distribución cuántica de claves](/learning/modules/computer-science/quantum-key-distribution).\n",
        "\n",
        "En Qiskit, cuando se realiza una medición, se envía a un registro clásico donde se almacena como un bit clásico. La creación de un circuito con una medida tiene este aspecto:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "56dfec5d-556b-486d-9cbf-0700582ec25c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/56dfec5d-556b-486d-9cbf-0700582ec25c-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(\n",
        "    1, 1\n",
        ")  # the second number is the number of classical bits in the circuit\n",
        "qc.measure(0, 0)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "45a53043-fdc8-4df2-b2c8-8b12ded1f400",
      "metadata": {},
      "source": [
        "<span id=\"circuits\" />\n",
        "\n",
        "## Circuitos\n",
        "\n",
        "Ahora que ya sabemos cómo funcionan los qubits, las puertas y las mediciones, ¡vamos a crear y ejecutar nuestro propio circuito cuántico! Para ello, tendremos que presentarte un útil flujo de trabajo llamado patrones Qiskit.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "a5adf2d9-4de5-4978-b509-05fb7381f238",
      "metadata": {},
      "source": [
        "<span id=\"qiskit-patterns-framework\" />\n",
        "\n",
        "### Marco de patrones Qiskit\n",
        "\n",
        "El marco de patrones Qiskit es un procedimiento general para abordar y resolver problemas con un ordenador cuántico. Consta de cuatro pasos:\n",
        "\n",
        "1. **Mapeando** nuestro problema a circuitos y operadores cuánticos\n",
        "2. **Optimización** del circuito para el hardware de destino\n",
        "3. **Ejecución** en el hardware de destino\n",
        "4. **Tratamiento posterior de** los resultados\n",
        "\n",
        "Para ilustrar estos pasos, implementaremos una versión *cuántica* del circuito de media escalera comentado anteriormente.\n",
        "\n",
        "<span id=\"1-mapping\" />\n",
        "\n",
        "#### 1. Cartografía\n",
        "\n",
        "El circuito sumador clásico utiliza una puerta XOR y una puerta AND para calcular los bits de suma y acarreo, respectivamente. Podemos adaptar estas puertas al contexto cuántico para hacer el sumador medio cuántico. En primer lugar, recordando que las puertas cuánticas son *reversibles*, no podemos simplemente sobrescribir las entradas. En su lugar, introducimos dos qubits auxiliares inicializados en $\\vert 0\\rangle$ para almacenar las salidas de suma y acarreo. Así, nuestro estado cuántico completo estará formado por los qubits $A$ y $B$, y los qubits suma y acarreo, que etiquetaremos $S$ y $C$ :\n",
        "\n",
        "$\\vert \\psi\\rangle = \\vert C S B A\\rangle$\n",
        "\n",
        "Ahora necesitamos puertas cuánticas que hagan lo mismo que las puertas XOR y AND en el circuito clásico.\n",
        "\n",
        "**SUMA:**\n",
        "\n",
        "Para el XOR, aplicamos dos CNOTs, cada uno con qubits de control $A$ y $B$ y qubit objetivo $S$ para ambos. Si $A$ y $B$ son diferentes, una de las puertas CNOT cambiará $S$ al estado $\\vert 1\\rangle$. Si $A$ y $B$ son ambos $\\vert 0\\rangle$, entonces no le pasa nada a $S$ y permanece en el estado $\\vert 0\\rangle$. Si $A$ y $B$ son ambos $\\vert 1\\rangle$, entonces el estado de $S$ cambiará dos veces, devolviéndolo al estado $\\vert 0\\rangle$.\n",
        "\n",
        "**Llevar:**\n",
        "\n",
        "Para el bit de acarreo, necesitamos algo que funcione como la clásica puerta AND.\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Comprueba tu comprensión\n",
        "\n",
        "Repasa las puertas de las que hemos hablado para ver si adivinas qué puerta cuántica utilizaremos en lugar de la puerta AND clásica:\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Respuesta\">\n",
        "    ¡Es la puerta Toffoli! Recuerde, la puerta Toffoli, o controlada-controlada-no, cambia el estado objetivo si y sólo si el qubit de control 0 Y el qubit de control 1 son ambos $\\vert 1\\rangle$. Por lo tanto, si el qubit objetivo comienza en el estado $\\vert 0\\rangle$, entonces tiene la misma acción que la puerta AND.\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "Así que ya tenemos todos los ingredientes que necesitamos para hacer el circuito cuántico:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "0bf14732-29fb-41c7-a4b3-94bd276ebc33",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/0bf14732-29fb-41c7-a4b3-94bd276ebc33-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# qubits: a, b, sum, carry\n",
        "qc = QuantumCircuit(4)\n",
        "\n",
        "# Choose values for A and B:\n",
        "a = 0\n",
        "b = 0\n",
        "\n",
        "# Prepare A and B qubits according to selected values:\n",
        "if a:\n",
        "    qc.x(0)\n",
        "if b:\n",
        "    qc.x(1)\n",
        "\n",
        "# XOR (sum) into qubit 2\n",
        "qc.cx(0, 2)\n",
        "qc.cx(1, 2)\n",
        "\n",
        "# AND (carry) into qubit 3\n",
        "qc.ccx(0, 1, 3)  # a AND b\n",
        "\n",
        "# measure\n",
        "qc.measure_all()\n",
        "\n",
        "\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cd129de5-0b73-44db-97ea-f819184e3661",
      "metadata": {},
      "source": [
        "Arriba está el diagrama del circuito de media escalera cuántica. Como se ha mencionado anteriormente, los hilos representan qubits $0$ a $3$ ordenados de arriba a abajo, y el registro de bits clásico es el hilo inferior de doble línea. Luego, leyendo de izquierda a derecha, vemos cómo se aplican las puertas a cada qubit viendo dónde aparecen las casillas en los cables correspondientes. Por último, al final se muestran las mediciones. Las mediciones colapsan los estados de los qubits en valores definidos $0$ o $1$, y los resultados se envían a un registro clásico.\n",
        "\n",
        "Una sutileza: aunque el esquema del circuito está dibujado de izquierda a derecha, al escribir la expresión matricial correspondiente debemos leerlo de derecha a izquierda. Esto se debe a que en la multiplicación de matrices, el operador más cercano al vector de estado actúa primero. Así, por ejemplo, el circuito anterior (ignorando las medidas) se escribiría como:\n",
        "\n",
        "$$\n",
        "CCNOT(q_0,q_1,q_3)CNOT(q_1, q_2)CNOT(q_0,q_2)\\vert q_3 q_2 q_1 q_0\\rangle\n",
        "$$\n",
        "\n",
        "<span id=\"2-optimizing\" />\n",
        "\n",
        "#### 2. Optimización:\n",
        "\n",
        "A continuación, tenemos que optimizar el circuito para que funcione en el hardware cuántico. Esta optimización se consigue mediante el transpilador, que traduce el circuito abstracto mostrado anteriormente en instrucciones que el ordenador cuántico entenderá. Asigna los qubits lógicos anteriores a qubits físicos reales en el procesador y reescribe las puertas en términos de su propio conjunto nativo de puertas que han sido optimizadas para funcionar en el ordenador cuántico. Por último, el transpilador también implementa algo llamado \"supresión y mitigación de errores\" para intentar minimizar el efecto de los errores en el resultado. Esto no es tan importante para nuestro circuito tan simple, pero si continúas en tu viaje por la computación cuántica para ejecutar circuitos más complicados, pronto verás el valor de la supresión y mitigación de errores. Si quieres saber más sobre esto, consulta el curso de Olivia Lane, [Quantum Computing in Practice](/learning/courses/quantum-computing-in-practice/introduction).\n",
        "\n",
        "En primer lugar, cargamos los paquetes necesarios para comunicarnos con los ordenadores cuánticos de IBM® y seleccionamos un backend en el que ejecutarlo. Podemos elegir el backend menos ocupado o seleccionar un backend específico cuyas propiedades conozcamos.\n",
        "\n",
        "A continuación encontrará un código para guardar sus credenciales la primera vez que las utilice. Asegúrate de borrar esta información del cuaderno después de guardarlo en tu entorno, para que tus credenciales no se compartan accidentalmente cuando compartas el cuaderno. Consulte [Configurar su cuenta IBM Cloud](/docs/guides/cloud-setup) e [Inicializar el servicio en un entorno no](/docs/guides/cloud-setup-untrusted) fiable para obtener más orientación.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "bdc5e025-8bf4-4fbc-af80-4404e2577511",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "ibm_fez\n"
          ]
        }
      ],
      "source": [
        "# Load the Qiskit Runtime service\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "# Load the Qiskit Runtime service\n",
        "\n",
        "# Syntax for first saving your token.  Delete these lines after saving your credentials.\n",
        "# QiskitRuntimeService.save_account(channel='ibm_quantum_platform',\n",
        "# instance = '<YOUR_IBM_INSTANCE_CRN>', token='<YOUR-API_KEY>', overwrite=True, set_as_default=True)\n",
        "# service = QiskitRuntimeService(channel='ibm_quantum_platform')\n",
        "\n",
        "# Load saved credentials\n",
        "service = QiskitRuntimeService()\n",
        "\n",
        "# Use the least busy backend, or uncomment the loading of a specific backend like \"ibm_brisbane\".\n",
        "backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)\n",
        "# backend = service.backend(\"ibm_brisbane\")\n",
        "print(backend.name)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4b4fb4cb-7e4a-47f4-a5d5-803b2d513a61",
      "metadata": {},
      "source": [
        "Ahora, utilizamos el transpilador para optimizar el circuito. Podemos elegir el nivel de optimización de 0 (sin optimización) a 3 (máxima optimización). Para ver lo que implica cada nivel, visite la guía de [niveles de optimización del transpilador Set](/docs/guides/set-optimization). El circuito resultante tendrá un aspecto significativamente diferente del circuito lógico que hicimos en nuestro paso de mapeo.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "ad106853-7416-4fb9-b8e3-c43bb81c9059",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/ad106853-7416-4fb9-b8e3-c43bb81c9059-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Transpile the circuit and optimize for running on the quantum computer selected\n",
        "# Step 2: Transpile\n",
        "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
        "\n",
        "target = backend.target\n",
        "pm = generate_preset_pass_manager(target=target, optimization_level=3)\n",
        "qc_isa = pm.run(qc)\n",
        "\n",
        "qc_isa.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d9c345cf-9a25-4b6f-a5ec-62a6cefe3f27",
      "metadata": {},
      "source": [
        "Un \"muestreador\" es una primitiva diseñada para muestrear los posibles estados resultantes de un circuito cuántico y recopilar estadísticas sobre qué estados podrían medirse y con qué probabilidad. Aquí importamos el muestrario Qiskit Runtime :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "13a3faee-256d-4038-b0bf-ef1100139a96",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Load the Runtime primitive and session\n",
        "from qiskit_ibm_runtime import SamplerV2 as Sampler\n",
        "\n",
        "sampler = Sampler(mode=backend)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3d392a16-51ae-4367-8b75-4abf520f6474",
      "metadata": {},
      "source": [
        "Si ha agotado el tiempo asignado a los ordenadores cuánticos reales o si no dispone de conexión a Internet, puede que prefiera utilizar un simulador. Para ello, ejecute la celda siguiente y descomente la línea asociada en el paso \"Ejecutar\".\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "bcc1cab6-73db-4c8e-96b6-af7137ab6bd1",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Load the backend sampler\n",
        "from qiskit.primitives import BackendSamplerV2\n",
        "\n",
        "# Load the Aer simulator and generate a noise model based on the currently-selected backend.\n",
        "from qiskit_aer import AerSimulator\n",
        "from qiskit_aer.noise import NoiseModel\n",
        "\n",
        "noise_model = NoiseModel.from_backend(backend)\n",
        "\n",
        "# Define a simulator using Aer, and use it in Sampler.\n",
        "backend_sim = AerSimulator(noise_model=noise_model)\n",
        "sampler_sim = BackendSamplerV2(backend=backend_sim)\n",
        "\n",
        "# Alternatively, load a fake backend with generic properties and define a simulator.\n",
        "# backend_gen = GenericBackendV2(num_qubits=18)\n",
        "# sampler_gen = BackendSamplerV2(backend=backend_gen)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6112fb67-3f51-4532-bb30-331b687cb43d",
      "metadata": {},
      "source": [
        "<span id=\"3-executing\" />\n",
        "\n",
        "#### 3. Ejecución\n",
        "\n",
        "Después de preparar el circuito, ¡ya podemos ejecutarlo en el ordenador cuántico!\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "0609b820-bb46-4a00-b33b-813ce8843ae1",
      "metadata": {},
      "outputs": [],
      "source": [
        "job = sampler.run([qc_isa], shots=100)\n",
        "# job = sampler_sim.run([qc_isa]) # uncomment if you want to run on a simulator\n",
        "res = job.result()\n",
        "counts = res[0].data.meas.get_counts()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fea26bd9-84c9-402f-bd7e-785754993af9",
      "metadata": {},
      "source": [
        "<span id=\"4-post-processing\" />\n",
        "\n",
        "#### 4. Postprocesamiento\n",
        "\n",
        "Ahora ya podemos ver los resultados Visualizaremos un histograma de las 100 muestras del circuito.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "a4efc93d-ed2e-406f-b335-deeaa661c55b",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "counts =  {'0000': 90, '0100': 4, '1100': 3, '0010': 3}\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/a4efc93d-ed2e-406f-b335-deeaa661c55b-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 17,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.visualization import plot_histogram\n",
        "\n",
        "print(\"counts = \", counts)\n",
        "plot_histogram(counts)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c228359b-7022-426a-ae7f-3599efb2231e",
      "metadata": {},
      "source": [
        "El histograma anterior muestra los resultados de las mediciones de los cuatro qubits al final del circuito. Un ordenador cuántico ideal con ruido cero habría medido los qubits para que tuvieran los mismos valores cada vez, pero en realidad, el ruido hará que algunas de las ejecuciones produzcan errores.\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Comprueba tu comprensión\n",
        "\n",
        "Utilizando la cadena de bits con el mayor número de conteos como sus valores para $A$, $B$, $S$, y $C$, verifique que el circuito sumador cuántico funcionó.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Respuesta\">\n",
        "    Tenemos que comprobar que $A+B = S+2 \\times C$. Recuerda que el orden de la cadena de bits sigue la notación little-endian, por lo que se lee `CSBA`.\n",
        "\n",
        "    En el histograma anterior, vemos que la cadena de bits `0000` es la dominante.\n",
        "\n",
        "    $0 + 0 = 0 + 0 \\times 2 = 0 ~\\checkmark$\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "Vuelve atrás y cambia los valores de $A$ y $B$ por $A=1$ y $B=1$ y repite los pasos de los patrones Qiskit para volver a ejecutar el circuito. Comprueba que el circuito sumador vuelve a funcionar.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Respuesta\">\n",
        "    Debería obtener un histograma en el que la cadena de bits dominante fuera `1011`:\n",
        "\n",
        "    $1 + 1 = 0 + 1 \\times 2 = 2 ~\\checkmark$\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "Una de las características añadidas de la semiescala *cuántica* sobre la semiescala clásica es que puede funcionar con entradas *cuánticas*. Es decir, puede \"sumar\" los qubits $A$ y $B$ aunque estén en estados de superposición. En la sección de Preguntas de Desafío, se te pedirá que prepares los qubits en superposiciones y veas lo que ocurre\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ca1d1257-d741-4f46-908b-73cef6bc8fc7",
      "metadata": {},
      "source": [
        "<span id=\"conclusion\" />\n",
        "\n",
        "## Conclusión\n",
        "\n",
        "Este módulo ha sido diseñado para proporcionarle una sólida comprensión de los principios básicos de la computación cuántica comparándola con la computación clásica. Hemos visto el circuito clásico de media escalera y luego te hemos mostrado cómo adaptar el circuito para que funcione con qubits en un ordenador cuántico. Ya estás listo para explorar los demás módulos de Qiskit en el aula\n",
        "\n",
        "<span id=\"critical-concepts\" />\n",
        "\n",
        "### Conceptos fundamentales:\n",
        "\n",
        "* A diferencia de los bits clásicos, que sólo pueden tomar los valores 0 y 1, los qubits también pueden estar en estados de **superposición** tanto de 0 como de 1.\n",
        "* Múltiples qubits pueden estar en superposición sobre las cadenas de bits clásicamente permitidas, denominadas **estados de base computacional**.\n",
        "* Se pueden **entrelazar** varios qubits de modo que el estado de uno dependa del estado del otro.\n",
        "* La convención Qiskit es utilizar **la notación little-endian**, que coloca el qubit menos significativo, $q_0$, en la posición más a la derecha y el qubit más significativo, $q_N$, más a la izquierda.\n",
        "* **Las puertas cuánticas** son operaciones reversibles que se representan mediante matrices unitarias que actúan sobre los vectores de estado cuántico. En esta notación, la matriz más cercana al vector (que está más a la derecha) actúa primero.\n",
        "* **Las mediciones** colapsan un estado de superposición cuántica en uno de sus estados permitidos clásicamente, con probabilidad igual al cuadrado de la amplitud del estado base computacional correspondiente en la superposición.\n",
        "* Los circuitos cuánticos suelen representarse mediante **diagramas de circuitos cuánticos**, en los que los qubits se representan como hilos horizontales y las puertas cuánticas aparecen a lo largo de estos hilos de izquierda a derecha.\n",
        "* Para ejecutar un circuito cuántico, utilizamos los cuatro pasos del flujo de trabajo **de los patrones Qiskit** : **Mapear**, **Optimizar**, **Ejecutar**, **Post-procesar**.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "34ccee8d-e9cc-45eb-ab30-8e8160ec9a5b",
      "metadata": {},
      "source": [
        "<span id=\"questions\" />\n",
        "\n",
        "## Preguntas\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "37265ba8-dc01-4aae-941f-6e051c62d7cc",
      "metadata": {},
      "source": [
        "<span id=\"true/false-questions\" />\n",
        "\n",
        "### Preguntas de verdadero/falso\n",
        "\n",
        "1. En un ordenador clásico, un bit sólo puede contener el valor 0 ó 1.\n",
        "\n",
        "2. El entrelazamiento significa que el estado de un qubit es independiente del estado de otro.\n",
        "\n",
        "3. Las puertas cuánticas suelen ser operaciones irreversibles.\n",
        "\n",
        "4. La convención Qiskit coloca el qubit menos significativo, $q_0$, en la posición más a la izquierda.\n",
        "\n",
        "5. La medición de un estado cuántico siempre da exactamente el mismo resultado si se repite muchas veces.\n",
        "\n",
        "6. La puerta de Hadamard crea superposición en un único qubit.\n",
        "\n",
        "7. Los circuitos cuánticos pueden incluir operaciones de medición que colapsen el estado de superposición en uno de los estados permitidos clásicamente.\n",
        "\n",
        "8. El número de estados clásicos posibles para $N$ bits es $2N$.\n",
        "\n",
        "9. Las probabilidades de resultado de las mediciones cuánticas vienen dadas por las amplitudes al cuadrado de los estados base clásicamente medibles.\n",
        "\n",
        "<span id=\"short-answer-questions\" />\n",
        "\n",
        "### Preguntas de respuesta corta\n",
        "\n",
        "1. ¿Cuáles son las principales diferencias entre un bit y un qubit?\n",
        "\n",
        "2. ¿Qué le ocurre a un estado cuántico cuando se mide?\n",
        "\n",
        "3. ¿Por qué utilizamos la notación little-endian en Qiskit?\n",
        "\n",
        "4. ¿Cuáles son los cuatro pasos del flujo de trabajo de los patrones Qiskit?\n",
        "\n",
        "<span id=\"challenge-questions\" />\n",
        "\n",
        "### Preguntas de desafío:\n",
        "\n",
        "1. En el módulo, sólo utilizamos el sumador para añadir estados permitidos clásicamente para $A$ y $B$. ¡Pero también podemos preparar $A$ y $B$ en superposiciones! Cambia el código para preparar cada qubit en una superposición igual de 0 y 1, luego ejecuta el nuevo circuito y obtén un nuevo histograma. ¿Qué ves? Explica lo que está ocurriendo.\n",
        "\n",
        "2. Descomposición de la puerta de Toffoli. Utilice `decompose()` para mostrar cómo se descompone la puerta de Toffoli en puertas de uno y dos qubits, y luego verifique esta construcción con la multiplicación de matrices. Tenga en cuenta que, aunque los diagramas de circuitos se leen de izquierda a derecha, las matrices se aplican a los estados cuánticos de derecha a izquierda\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "in_page_toc_max_heading_level": 2,
    "in_page_toc_min_heading_level": 2,
    "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
}