{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "3e8391e9-be00-46b0-81a9-5474ae778663",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Teletransporte cuántico\"\n",
        "description: \"Explora cómo la teletransportación cuántica transfiere un estado cuántico de un lugar a otro utilizando los principios del entrelazamiento cuántico.\"\n",
        "---\n",
        "\n",
        "<span id=\"quantum-teleportation\" />\n",
        "\n",
        "# Teletransporte cuántico\n",
        "\n",
        "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 IBM Cloud](/docs/guides/cloud-setup).\n",
        "\n",
        "Este módulo fue probado y utilizó 14 segundos de tiempo QPU. Esto es sólo una estimación. Su uso real puede variar.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "0df1108e-f1ac-4e75-96c2-3d8b5992504e",
      "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": "404ed202-a761-4e82-a480-ce59d4b04adf",
      "metadata": {},
      "source": [
        "Vea el tutorial del módulo de la Dra. Katie McCormick a continuación, o haga clic [aquí](https://youtu.be/jxqnzltpDdE?si=UVL58hFOOWe2Q9qI) para verlo en YouTube.\n",
        "\n",
        "***\n",
        "\n",
        "<IBMVideo id=\"134413680\" title=\"Katie McCormick desmitifica el teletransporte cuántico y nos muestra algunos ejemplos con Qiskit.\" />\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a200b899-0c56-4f69-a7ba-0ca4d83e47cd",
      "metadata": {},
      "source": [
        "<span id=\"introduction-and-background\" />\n",
        "\n",
        "## Introducción y antecedentes\n",
        "\n",
        "El teletransporte cuántico es una técnica de la física cuántica que permite transferir información cuántica de un lugar a otro sin mover físicamente las partículas. A diferencia del concepto de ciencia ficción de teletransporte, este proceso no implica transportar materia. En su lugar, se basa en el principio del entrelazamiento cuántico, por el que dos partículas quedan vinculadas independientemente de la distancia. Mediante una serie de mediciones precisas y comunicación clásica, el estado cuántico de una partícula puede recrearse en otra partícula en un lugar distante, \"teletransportando\" de hecho la información cuántica. En este módulo veremos cómo funciona matemáticamente y, a continuación, pondremos en práctica el teletransporte cuántico en un ordenador cuántico real. La introducción aquí será breve; para más antecedentes sobre la información cuántica, y más explicaciones sobre el teletransporte, recomendamos el curso de John Watrous sobre los [Fundamentos de la información cuántica](/learning/courses/basics-of-quantum-information), y en particular la sección sobre [Teletransporte.](/learning/courses/basics-of-quantum-information/entanglement-in-action/quantum-teleportation)\n",
        "\n",
        "Los bits clásicos pueden estar en estado 0 ó 1. Los bits cuánticos (qubits) pueden encontrarse en estados cuánticos denominados $|0\\rangle$ y $|1\\rangle$ y también en combinaciones lineales de estos estados, denominadas \"superposiciones\", como $|\\psi\\rangle = \\alpha_0|0\\rangle +\\alpha_1|1\\rangle$, con $\\alpha_0,\\alpha_1 \\in \\mathbb{C},$ y $|\\alpha_0|^2+|\\alpha_1|^2 = 1.$. Aunque los estados pueden existir en esta superposición, una medición del estado lo \"colapsará\" en los estados $|0\\rangle$ o $|1\\rangle$. Los parámetros $a$ y $b$ están relacionados con la probabilidad de cada resultado de medición según\n",
        "\n",
        "$$\n",
        "P_0 = |\\alpha_0|^2\n",
        "$$\n",
        "\n",
        "$$\n",
        "P_1 = |\\alpha_1|^2\n",
        "$$\n",
        "\n",
        "De ahí la restricción de que $|\\alpha_0|^2+|\\alpha_1|^2 = 1.$\n",
        "\n",
        "Otra característica clave es que los bits cuánticos pueden estar \"enredados\", lo que significa que la medición de un qubit puede afectar al resultado de la medición de otro qubit enredado. Entender en qué se diferencia el entrelazamiento de las simples correlaciones clásicas es un poco complicado. Expliquemos primero nuestra notación. Llama a dos qubits pertenecientes al amigo 0 (Alice) y al amigo 1 (Bob), y cada uno en el estado $|0\\rangle$\n",
        "\n",
        "$$\n",
        "|0\\rangle_B|0\\rangle_A\n",
        "$$\n",
        "\n",
        "or\n",
        "\n",
        "$$\n",
        "|0\\rangle_1|0\\rangle_0\n",
        "$$\n",
        "\n",
        "a veces abreviado simplemente como\n",
        "\n",
        "$$\n",
        "|00\\rangle\n",
        "$$\n",
        "\n",
        "Observe que el qubit con el número (o letra) más bajo está más a la derecha. Esta es una convención llamada notación \"little-endian\", utilizada en todo Qiskit.\n",
        "Si el estado de dos qubits de los amigos es $|00\\rangle,$ y miden el estado de sus respectivos qubits, cada uno encontrará un 0. Del mismo modo, si los qubits estuvieran en el estado $|11\\rangle,$, cada una de sus mediciones daría un 1. Esto no difiere del caso clásico. Sin embargo, en computación cuántica, podemos combinar esto con superposición para obtener estados como\n",
        "\n",
        "$$\n",
        "\\frac{1}{\\sqrt{2}}(|00\\rangle+|11\\rangle)\n",
        "$$\n",
        "\n",
        "En un estado como este, si Alice y Bob tienen qubits en el estado 0 o 1 aún no se sabe, ni siquiera está determinado por la naturaleza, y sin embargo sabemos que medirán el mismo estado para su qubit. Por ejemplo, si Bob mide que su qubit está en el estado $|0\\rangle,$, la única forma de que eso ocurra es que la medición haya colapsado el estado de los dos qubits a uno de los dos estados posibles, concretamente a $|00\\rangle.$. Eso deja al qubit de Alice también en el estado $|0\\rangle$.\n",
        "\n",
        "El entrelazamiento de qubits de esta forma no requiere que los qubits permanezcan físicamente cerca unos de otros. En otras palabras, podríamos entrelazar qubits, separarlos a una gran distancia y utilizar su entrelazamiento para enviar información. Un estado entrelazado como el anterior es una unidad básica de entrelazamiento, y a veces se denomina \"e-bit\", un único bit de entrelazamiento. Estos e-bits pueden considerarse recursos en la comunicación cuántica, ya que cada e-bit compartido entre interlocutores distantes puede utilizarse, como esbozamos aquí, para trasladar información de un lugar a otro.\n",
        "\n",
        "Lo primero que piensan muchas personas que se enteran de esto por primera vez es que viola la relatividad: ¿podemos usar esto para enviar información más rápido que la luz? Por todos los medios, sigamos cuestionando y probando las reglas científicas, pero desgraciadamente esto no nos permitirá enviar información más rápido que la luz, por razones que quedarán claras a lo largo de este módulo. Spoiler: sorprendentemente NO se debe a la velocidad a la que se propaga este colapso, que sí parece suceder más rápido que la luz [\\[1\\]](https://www.nature.com/articles/nature15759).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4ce474e6-cea7-4327-9742-9e1a7dd468b0",
      "metadata": {},
      "source": [
        "Empezamos con dos colaboradores, Alice y Bob, que inicialmente se encuentran en el mismo lugar y pueden trabajar juntos en los mismos qubits. Estos colaboradores entrelazarán sus qubits. Después se separarán en dos lugares geográficos distintos, llevando consigo sus respectivos qubits. Alice obtendrá entonces información cuántica sobre un nuevo qubit Q. No hacemos suposiciones sobre la información de Q. El estado de Q podría ser un secreto desconocido para Alicia; podría ser desconocido para todas las personas. Pero Alice tiene la tarea de transferir la información sobre Q a Bob. Lo hará mediante teletransporte cuántico.\n",
        "\n",
        "Para lograrlo, necesitaremos conocer algunas operaciones cuánticas o \"puertas\".\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "03fe38b1-66fe-4c50-8403-d8c64197b5c6",
      "metadata": {},
      "source": [
        "<span id=\"quantum-operators-gates\" />\n",
        "\n",
        "## Operadores cuánticos (puertas)\n",
        "\n",
        "Si ya conoce las puertas cuánticas, puede saltarse esta sección. Si quiere entender mejor estas puertas, consulte [Fundamentos de la información cuántica](/learning/courses/basics-of-quantum-information), especialmente las dos primeras lecciones, en IBM Quantum Learning.\n",
        "\n",
        "Para este protocolo de teletransporte utilizaremos principalmente dos tipos de puertas cuánticas: la puerta Hadamard y la puerta CNOT. Otros desempeñarán un papel menos importante: la puerta $X$, la puerta $Z$ y la puerta SWAP.\n",
        "\n",
        "Este módulo puede completarse con conocimientos muy limitados de álgebra lineal, pero a veces puede ser útil visualizar las puertas de la mecánica cuántica utilizando matrices y vectores. Así que presentamos aquí también las formas matriciales/vectoriales de las puertas/estados cuánticos.\n",
        "\n",
        "Los estados que ya hemos presentado se eligen (en parte por convención y en parte por restricciones) para que tengan formas vectoriales:\n",
        "\n",
        "$$\n",
        "|0\\rangle = \\begin{pmatrix}1 \\\\ 0\\end{pmatrix}\n",
        "$$\n",
        "\n",
        "$$\n",
        "|1\\rangle = \\begin{pmatrix}0 \\\\ 1\\end{pmatrix}\n",
        "$$\n",
        "\n",
        "De este modo, un estado arbitrario $|\\psi\\rangle = a|0\\rangle+b|1\\rangle$ puede escribirse como\n",
        "\n",
        "$$\n",
        "|\\psi\\rangle =\\begin{pmatrix}a \\\\ b\\end{pmatrix}\n",
        "$$\n",
        "\n",
        "Se puede elegir cómo extender la notación a los estados de qubits múltiples, pero la opción que se presenta a continuación es bastante estándar:\n",
        "\n",
        "$$\n",
        "|00\\rangle = \\begin{pmatrix}1 \\\\ 0 \\\\ 0 \\\\ 0\\end{pmatrix},|01\\rangle = \\begin{pmatrix}0 \\\\ 1 \\\\ 0 \\\\ 0\\end{pmatrix},\n",
        "|10\\rangle = \\begin{pmatrix}0 \\\\ 0 \\\\ 1 \\\\0\\end{pmatrix},|11\\rangle = \\begin{pmatrix}0 \\\\ 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",
        "**H Puerta de Hadamard:** Crea un estado de superposición. Puerta single-qubit.\n",
        "\n",
        "$$\n",
        "H|0\\rangle = \\frac{1}{\\sqrt{2}}\\left(|0\\rangle+|1\\rangle\\right),\n",
        "$$\n",
        "\n",
        "$$\n",
        "H|1\\rangle = \\frac{1}{\\sqrt{2}}\\left(|0\\rangle-|1\\rangle\\right)\n",
        "$$\n",
        "\n",
        "$$\n",
        "H=\\frac{1}{\\sqrt{2}}\\begin{pmatrix} 1 & 1 \\\\ 1 & -1 \\end{pmatrix}\n",
        "$$\n",
        "\n",
        "Un circuito con una puerta Hadamard se realiza de la siguiente manera:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "a66b8ef2-6660-45b8-97bd-dbc98db49857",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/quantum-teleportation/extracted-outputs/a66b8ef2-6660-45b8-97bd-dbc98db49857-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.h(0)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "19b06d0f-0811-48aa-bf5d-a575f7b63876",
      "metadata": {},
      "source": [
        "**Puerta CNOT Controlada-NOT:** Esta puerta utiliza dos qubits: uno de control y otro de destino. Comprueba el estado de un qubit de control que no ha cambiado. Pero si el qubit de control está en el estado $|1\\rangle$, la puerta cambia el estado del qubit objetivo; si el estado del qubit de control es $|0\\rangle$ no se produce 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})|BA\\rangle.$\n",
        "\n",
        "$$\n",
        "CNOT(A,B)|00\\rangle = |00\\rangle, \\\\ CNOT(A,B)|01\\rangle = |11\\rangle, \\\\ CNOT(A,B)|10\\rangle = |10\\rangle, \\\\ CNOT(A,B)|11\\rangle = |01\\rangle\n",
        "$$\n",
        "\n",
        "A veces puede ver CNOT escrito con el orden del control y el objetivo simplemente implícito. Pero no existe tal ambigüedad en el código ni en los diagramas de circuitos.\n",
        "\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",
        "\n",
        "Una puerta CNOT tiene un aspecto un poco diferente en un circuito, ya que requiere dos qubits. Así es como se aplica:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "df5acfc1-feb8-4008-8e51-d9709352edde",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/quantum-teleportation/extracted-outputs/df5acfc1-feb8-4008-8e51-d9709352edde-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(2)\n",
        "qc.cx(0, 1)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "131d90c7-6ef3-4c32-a01b-52da9f8e0e83",
      "metadata": {},
      "source": [
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Comprueba tu comprensión\n",
        "\n",
        "La mayoría de las puertas tienen la misma forma matricial en Qiskit que en cualquier otro lugar. Pero la puerta CNOT actúa sobre dos qubits, por lo que, de repente, el orden de los qubits se convierte en un problema. Los textos que tratan sobre los qubits $|q_0,q_1,...\\rangle$ presentan una forma matricial diferente para sus puertas CNOT. Comprueba mediante una multiplicación matricial explícita que la matriz CNOT anterior tiene la acción correcta sobre el estado $|01\\rangle.$\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Respuesta\">\n",
        "    $CNOT|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} = |11\\rangle$\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2c1a61f3-770a-443e-8e01-26fc1106f92b",
      "metadata": {},
      "source": [
        "**$X$ Puerta** : Equivale a una operación NOT. Puerta single-qubit.\n",
        "\n",
        "$$\n",
        "X|0\\rangle = |1\\rangle,\\\\X|1\\rangle=|0\\rangle\n",
        "$$\n",
        "\n",
        "$$\n",
        "X=\\begin{pmatrix} 0 & 1 \\\\ 1 & 0 \\end{pmatrix}\n",
        "$$\n",
        "\n",
        "En Qiskit, crear un circuito con una puerta $X$ tiene este aspecto:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "5a23a576-385b-4a7c-899d-67ef4bb0bfed",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/quantum-teleportation/extracted-outputs/5a23a576-385b-4a7c-899d-67ef4bb0bfed-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(1)\n",
        "qc.x(0)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "81eaa9dc-740a-4a99-8950-fc7724c6440b",
      "metadata": {},
      "source": [
        "**$Z$ Puerta** : Añade una \"fase\" a un estado (un prefactor, que en los casos de los estados propios Z $|0\\rangle$ y $|1\\rangle$ puede ser un 1 o -1, respectivamente). Puerta single-qubit.\n",
        "\n",
        "$$\n",
        "Z|0\\rangle = |0\\rangle,\\\\Z|1\\rangle=-|1\\rangle\n",
        "$$\n",
        "\n",
        "$$\n",
        "Z=\\begin{pmatrix} 1 & 0 \\\\ 0 & -1 \\end{pmatrix}\n",
        "$$\n",
        "\n",
        "En Qiskit, crear un circuito con una puerta $Z$ tiene este aspecto:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "653b2420-eaa8-41ef-8262-3a9efa638cd3",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/quantum-teleportation/extracted-outputs/653b2420-eaa8-41ef-8262-3a9efa638cd3-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(1)\n",
        "qc.z(0)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "476c82d2-4c58-4c25-8f0d-646cd4afb757",
      "metadata": {},
      "source": [
        "<span id=\"theory\" />\n",
        "\n",
        "## teoría\n",
        "\n",
        "Expongamos el protocolo del teletransporte cuántico utilizando las matemáticas. A continuación, en la siguiente sección, realizaremos esta configuración utilizando un ordenador cuántico.\n",
        "\n",
        "**Alice y Bob entrelazan sus qubits:** Inicialmente, el qubit de Alice y el qubit de Bob están cada uno, por separado, en el estado $|0\\rangle$ (una buena suposición y también la inicialización correcta para los ordenadores cuánticos IBM® ). Podemos escribirlo como $|0\\rangle_B|0\\rangle_A$ o simplemente como $|00\\rangle$. Calculemos lo que ocurre cuando Alice y Bob actúan con la puerta Hadamard sobre el qubit de Alice, y luego una puerta CNOT con el qubit de Alice como control y el de Bob como objetivo:\n",
        "\n",
        "$$\n",
        "\\begin{aligned}\n",
        "CNOT(A,B)H_A |0\\rangle_B|0\\rangle_A &= CNOT(A,B)|0\\rangle_B\\frac{1}{\\sqrt{2}}\\left(|0\\rangle_A+|1\\rangle_A\\right)\\\\\n",
        "&=\\frac{1}{\\sqrt{2}}\\left(CNOT(A,B)|0\\rangle_B|0\\rangle_A+CNOT(A,B)|0\\rangle_B|1\\rangle_A\\right)\\\\\n",
        "&=\\frac{1}{\\sqrt{2}}\\left(|0\\rangle_B|0\\rangle_A+|1\\rangle_B|1\\rangle_A\\right)\n",
        "\\end{aligned}\n",
        "$$\n",
        "\n",
        "Nótese que ahora los qubits de Alice y Bob están entrelazados. Aunque todavía no está determinado por la naturaleza si sus dos qubits están en el estado $|0\\rangle$ o en el estado $|1\\rangle$, se sabe que sus qubits están en el mismo estado.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b51aed85-2976-4c46-a1d8-07dba8af78fe",
      "metadata": {},
      "source": [
        "**Alice y Bob se separan:** Los dos amigos mueven sus qubits a nuevas ubicaciones, posiblemente muy alejadas. Esto viene con muchas advertencias: no es trivial mover la información cuántica sin perturbarla. Pero se puede mover, y de hecho lo harás en este módulo. Sin embargo, hay que tener en cuenta que es de esperar que se produzcan algunos errores cuando movemos mucho la información cuántica.\n",
        "\n",
        "**Se introduce Q:** El estado secreto se prepara en el qubit Q:\n",
        "\n",
        "$$\n",
        "|\\psi\\rangle_Q = \\alpha_0 |0\\rangle_Q + \\alpha_1 |1\\rangle_Q\n",
        "$$\n",
        "\n",
        "En este punto Q es simplemente adyacente al qubit de Alice (A). No ha habido entrelazamiento, por lo que el estado cuántico de los tres qubits juntos se puede escribir como:\n",
        "\n",
        "$$\n",
        "|\\psi\\rangle_{AB}|\\psi\\rangle_Q = \\frac{1}{\\sqrt{2}}\\left(|0\\rangle_B|0\\rangle_A+|1\\rangle_B|1\\rangle_A\\right)\\left(\\alpha_0 |0\\rangle_Q + \\alpha_1 |1\\rangle_Q\\right).\n",
        "$$\n",
        "\n",
        "El objetivo es trasladar la información sobre Q desde la ubicación de Alice a la de Bob. En este momento, no estamos haciendo ninguna afirmación o exigencia sobre el secreto o la velocidad de transferencia de la información. Simplemente estamos explorando cómo la información puede pasar de Alice a Bob.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cd8f8dab-601f-42b6-8b1e-027568f8726c",
      "metadata": {},
      "source": [
        "Dado que la información comienza en Q, supondremos que Q tiene asignado el número más bajo en los números de qubit, de forma que la notación little endian hace que Q sea el qubit situado más a la derecha en las matemáticas que aparecen a continuación.\n",
        "\n",
        "Alice **entrelaza los qubits A y Q:** Alice opera ahora con una puerta CNOT con su propio qubit como control y Q como objetivo, luego aplica una puerta Hadamard a Q.  Calculemos el estado de tres qubits después de esa operación:\n",
        "\n",
        "$$\n",
        "\\begin{aligned}\n",
        "H_Q CNOT(A,Q)|\\psi\\rangle_{AB}|\\psi\\rangle_Q &= H_Q CNOT(A,Q)\\frac{1}{\\sqrt{2}}\\left(|0\\rangle_B|0\\rangle_A+|1\\rangle_B|1\\rangle_A\\right)\\left(\\alpha_0 |0\\rangle_Q + \\alpha_1 |1\\rangle_Q\\right)\\\\\n",
        "&= H_Q CNOT(A,Q)\\frac{1}{\\sqrt{2}}\\left(\\left(\\alpha_0 |0\\rangle_B|0\\rangle_A|0\\rangle_Q + \\alpha_1 |0\\rangle_B|0\\rangle_A|1\\rangle_Q\\right)+\\left(\\alpha_0 |1\\rangle_B|1\\rangle_A|0\\rangle_Q + \\alpha_1 |1\\rangle_B|1\\rangle_A|1\\rangle_Q\\right)\\right)\\\\\n",
        "&= H_Q \\frac{1}{\\sqrt{2}}\\left(\\alpha_0 |0\\rangle_B|0\\rangle_A|0\\rangle_Q + \\alpha_1 |0\\rangle_B|1\\rangle_A|1\\rangle_Q+\\alpha_0 |1\\rangle_B|1\\rangle_A|0\\rangle_Q + \\alpha_1 |1\\rangle_B|0\\rangle_A|1\\rangle_Q\\right)\\\\\n",
        "&= \\frac{1}{2}\\left(\\alpha_0 |0\\rangle_B|0\\rangle_A|0\\rangle_Q + \\alpha_0 |0\\rangle_B|0\\rangle_A|1\\rangle_Q + \\alpha_1 |0\\rangle_B|1\\rangle_A|0\\rangle_Q-\\alpha_1 |0\\rangle_B|1\\rangle_A|1\\rangle_Q\\right)\\\\\n",
        "&+\\frac{1}{2}\\left(\\alpha_0 |1\\rangle_B|1\\rangle_A|0\\rangle_Q + \\alpha_0 |1\\rangle_B|1\\rangle_A|1\\rangle_Q + \\alpha_1 |1\\rangle_B|0\\rangle_A|0\\rangle_Q - \\alpha_1 |1\\rangle_B|0\\rangle_A|1\\rangle_Q\\right)\n",
        "\\end{aligned}\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "78aaf4c7-2775-483e-91cd-11d400793776",
      "metadata": {},
      "source": [
        "Dado que A y Q están en el mismo lugar, agrupemos los términos anteriores según los resultados de las mediciones en los qubits A y Q:\n",
        "\n",
        "$$\n",
        "\\begin{aligned}\n",
        "|\\psi\\rangle = \\frac{1}{2}\\left((\\alpha_0 |0\\rangle_B+\\alpha_1 |1\\rangle_B)|0\\rangle_A|0\\rangle_Q +  (\\alpha_0 |0\\rangle_B-\\alpha_1 |1\\rangle_B)|0\\rangle_A|1\\rangle_Q + (\\alpha_1 |0\\rangle_B+\\alpha_0 |1\\rangle_B)|1\\rangle_A|0\\rangle_Q+ (-\\alpha_1 |0\\rangle_B+\\alpha_0 |1\\rangle_B)|1\\rangle_A|1\\rangle_Q \\right)\\\\\n",
        "\\end{aligned}\n",
        "$$\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Comprueba tu comprensión\n",
        "\n",
        "Teniendo en cuenta la expresión anterior para los estados de los tres qubits, ¿cuál es la probabilidad de que una medición de los qubits A y Q dé como resultado un $|0\\rangle_A|0\\rangle_Q?$\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Respuesta\">\n",
        "    25%. Para ver esto, recuerde que el estado de Bob debe ser normalizado, por lo que $ |_A \\langle0|_Q\\langle0| \\frac{1}{2} |0\\rangle_A|0\\rangle_Q (\\alpha_0 |0\\rangle_B+\\alpha_1 |1\\rangle_B)|^2 = \\frac{1}{4}|(\\alpha_0 |0\\rangle_B+\\alpha_1 |1\\rangle_B)|^2 = \\frac{1}{4}$\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8df3034b-9807-487b-a046-e689061cb026",
      "metadata": {},
      "source": [
        "Ahora, Alice puede medir los qubits A y Q. No puede controlar el resultado de esa medición, ya que las mediciones cuánticas son probabilísticas. Así que cuando ella mide, hay 4 resultados posibles y los 4 son igualmente probables: $|0\\rangle_A|0\\rangle_Q,$ $|0\\rangle_A|1\\rangle_Q,$ $|1\\rangle_A|0\\rangle_Q,$ y $|1\\rangle_A|1\\rangle_Q.$ Tenga en cuenta que cada resultado tiene diferentes implicaciones para el qubit de Bob. Por ejemplo, si Alice encuentra que sus qubits están en $|0\\rangle_A|0\\rangle_Q,$ que ha colapsado todo el estado cuántico de 3 qubits a $(\\alpha_0|0\\rangle_B+\\alpha_1|1\\rangle_B)|0\\rangle_A|0\\rangle_Q.$. Otros resultados de medición para Alice producen diferentes estados para Bob. Se recogen en el cuadro siguiente.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "99e01c8f-e6e1-4679-8e48-1e33a1b78e63",
      "metadata": {},
      "source": [
        "| Resultado Alice                      | Estado de Bob                                        | Instrucciones a Bob | Resultado                                           |\n",
        "| ------------------------------------ | ---------------------------------------------------- | ------------------- | --------------------------------------------------- |\n",
        "| $ \\vert 0\\rangle_A \\vert 0\\rangle_Q$ | $\\alpha_0\\vert 0\\rangle_B+\\alpha_1\\vert 1\\rangle_B$  | Ninguna             | $\\alpha_0\\vert 0\\rangle_B+\\alpha_1\\vert 1\\rangle_B$ |\n",
        "| $ \\vert 0\\rangle_A \\vert 1\\rangle_Q$ | $\\alpha_0\\vert 0\\rangle_B-\\alpha_1\\vert 1\\rangle_B$  | $Z$                 | $\\alpha_0\\vert 0\\rangle_B+\\alpha_1\\vert 1\\rangle_B$ |\n",
        "| $ \\vert 1\\rangle_A \\vert 0\\rangle_Q$ | $\\alpha_1\\vert 0\\rangle_B+\\alpha_0\\vert 1\\rangle_B$  | $X$                 | $\\alpha_0\\vert 0\\rangle_B+\\alpha_1\\vert 1\\rangle_B$ |\n",
        "| $ \\vert 1\\rangle_A \\vert 1\\rangle_Q$ | $-\\alpha_1\\vert 0\\rangle_B+\\alpha_0\\vert 1\\rangle_B$ | $X$ entonces $Z$    | $\\alpha_0\\vert 0\\rangle_B+\\alpha_1\\vert 1\\rangle_B$ |\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ff32d084-31ea-4408-b3cb-b5bebb845a3b",
      "metadata": {},
      "source": [
        "Para todos los resultados de medición posibles en los qubits de Alice, el qubit de Bob queda en un estado vagamente parecido al estado secreto originalmente en Q. En el caso de que Alice mida $|0\\rangle_C|0\\rangle_A$ (la primera fila de la tabla), ¡el qubit de Bob queda exactamente en el estado secreto! En los demás casos, hay algo raro en el Estado. Los coeficientes ( $\\alpha$ 's) están intercambiados, o hay un signo \"-\" donde debería haber un signo \"+\", o ambas cosas. Para modificar el qubit de Bob y hacerlo exactamente igual al estado secreto, Alice debe llamar a Bob (utilizar algún medio de comunicación clásica) y decirle que realice operaciones adicionales en su qubit, como se indica en la tabla. Por ejemplo, en la tercera fila se intercambian los coeficientes. Si Alice llama a Bob y le dice que aplique una puerta $X$ a su qubit, éste cambia un $|0\\rangle$ por un $|1\\rangle$ y viceversa, y sale el estado secreto.\n",
        "\n",
        "Ahora debería estar claro por qué no podemos utilizar esta configuración para enviar información más rápido que la luz. Podríamos tener suerte y medir $|0\\rangle_A|0\\rangle_Q,$ lo que significa que Bob tiene exactamente el estado secreto, al instante. Pero Bob no lo sabe hasta que le llamamos y le decimos \"Hemos medido $|0\\rangle_A|0\\rangle_Q$, así que no tienes que hacer nada\"\n",
        "\n",
        "En el experimento mental, los qubits suelen separarse físicamente y llevarse a un nuevo lugar. IBM® los ordenadores cuánticos utilizan qubits de estado sólido en un chip que no pueden separarse. Así, en lugar de trasladar a Alice y Bob a lugares diferentes, separaremos la información en el propio chip utilizando las llamadas \"puertas de intercambio\" para trasladar la información de un qubit a otro.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "efa0afed-97e7-42fd-a06d-7c095e703537",
      "metadata": {},
      "source": [
        "<span id=\"experiment-1-basic-teleportation\" />\n",
        "\n",
        "## Experimento 1: Teletransportación básica\n",
        "\n",
        "IBM Quantum recomienda abordar los problemas de computación cuántica utilizando un marco que denominamos \"patrones Qiskit\". Consta de los siguientes pasos.\n",
        "\n",
        "* Paso 1: Representar el problema en un circuito cuántico\n",
        "* Paso 2: Optimiza tu circuito para que funcione en hardware cuántico real\n",
        "* Paso 3: Ejecute su trabajo en los ordenadores cuánticos de IBM utilizando primitivas de ejecución\n",
        "* Paso 4: Postprocesamiento de los resultados\n",
        "\n",
        "<span id=\"step-1-map-your-problem-to-a-quantum-circuit\" />\n",
        "\n",
        "### Paso 1: Asigne su problema a un circuito cuántico\n",
        "\n",
        "Toda la matemática que hicimos arriba fue esbozar el paso 1. Vamos a ponerlo en práctica ahora, ¡construyendo nuestro circuito cuántico utilizando Qiskit! Empezamos creando un circuito cuántico con tres qubits, y entrelazando los dos qubits de Alice y Bob. Consideraremos que son los qubits 1 y 2, y reservaremos el qubit 0 para el estado secreto.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "6e3e0d07-b52f-4e17-9233-0a00065f2d77",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/quantum-teleportation/extracted-outputs/6e3e0d07-b52f-4e17-9233-0a00065f2d77-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Step 1: Map your problem to a quantum circuit\n",
        "\n",
        "# Import some general packages\n",
        "from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister\n",
        "import numpy as np\n",
        "\n",
        "# Define registers\n",
        "secret = QuantumRegister(1, \"Q\")\n",
        "Alice = QuantumRegister(1, \"A\")\n",
        "Bob = QuantumRegister(1, \"B\")\n",
        "\n",
        "cr = ClassicalRegister(3, \"c\")\n",
        "\n",
        "qc = QuantumCircuit(secret, Alice, Bob, cr)\n",
        "\n",
        "# We entangle Alice's and Bob's qubits as in our work above.\n",
        "# We apply a Hadamard gate and then a CNOT gate.\n",
        "# Note that the second argument in the CNOT gate is the target.\n",
        "qc.h(Alice)\n",
        "qc.cx(Alice, Bob)\n",
        "\n",
        "# Inserting a barrier changes nothing about the logic. It just allows us to\n",
        "# force gates to be positioned in \"layers\".\n",
        "qc.barrier()\n",
        "\n",
        "# Now we will use random variables to create the secret state.\n",
        "# Don't worry about the \"u\" gate and the details.\n",
        "np.random.seed(42)  # fixing seed for repeatability\n",
        "theta = np.random.uniform(0.0, 1.0) * np.pi  # from 0 to pi\n",
        "varphi = np.random.uniform(0.0, 2.0) * np.pi  # from 0 to 2*pi\n",
        "\n",
        "# Assign the secret state to the qubit on the other side of Alice's (qubit 0), labeled Q\n",
        "qc.u(theta, varphi, 0.0, secret)\n",
        "qc.barrier()\n",
        "\n",
        "# Now entangle Q and Alice's qubits as in the discussion above.\n",
        "qc.cx(secret, Alice)\n",
        "qc.h(secret)\n",
        "qc.barrier()\n",
        "\n",
        "# Now Alice measures her qubits, and stores the outcomes in the \"classical registers\" cr[]\n",
        "qc.measure(Alice, cr[1])\n",
        "qc.measure(secret, cr[0])\n",
        "\n",
        "# Now we insert some conditional logic. If Alice measures Q in a \"1\" we need a Z gate, and if Alice\n",
        "# measures A in a \"1\" we need an X gate (see the table).\n",
        "with qc.if_test((cr[1], 1)):\n",
        "    qc.x(Bob)\n",
        "with qc.if_test((cr[0], 1)):\n",
        "    qc.z(Bob)\n",
        "\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2802dfbf-e3cb-4bd8-80cd-83ec972c7bd9",
      "metadata": {},
      "source": [
        "Eso es todo lo que tenemos que hacer para que el estado de Alice sea teletransportado a Bob. Sin embargo, recordemos que cuando medimos un estado cuántico $\\alpha_0 |0\\rangle+\\alpha_1|1\\rangle$ encontramos o $|0\\rangle$ o $|1\\rangle.$ Así que al final de todo esto, Bob definitivamente tiene el estado secreto de Alice, pero no podemos verificarlo fácilmente con una medición. Para que una medición nos diga que lo hemos hecho correctamente, tenemos que hacer un truco. Teníamos un operador etiquetado \"U\" de \"unitario\" que utilizábamos para preparar el estado secreto de Alice. Podemos aplicar la inversa de U al final de nuestro circuito. Si U mapeó el estado $|0\\rangle$ de Alice a $\\alpha_0 |0\\rangle+\\alpha_1|1\\rangle$, entonces el inverso de U mapeará el $\\alpha_0 |0\\rangle+\\alpha_1|1\\rangle$ de Bob de vuelta a $|0\\rangle.$ Así que esta última parte no se haría necesariamente si el objetivo fuera sólo mover información cuántica. Esto sólo se hace para que nos controlemos a nosotros mismos.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "dac9d281-6c57-4e70-9a61-74efa5d4bdc2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/quantum-teleportation/extracted-outputs/dac9d281-6c57-4e70-9a61-74efa5d4bdc2-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Add the inverse of U and measure Bob's qubit.\n",
        "qc.barrier()\n",
        "\n",
        "qc.u(theta, varphi, 0.0, Bob).inverse()  # inverse of u(theta,varphi,0.0)\n",
        "qc.measure(Bob, cr[2])  # add measurement gate\n",
        "\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bd6643de-e67f-44f6-b83d-d7ea9f314eb8",
      "metadata": {},
      "source": [
        "Así que si hemos hecho esto correctamente, nuestra medición en el qubit de Bob debería dar como resultado un estado $|0\\rangle$. Por supuesto, estas mediciones son probabilísticas. Así que si hay incluso una pequeña posibilidad de medir el qubit de Bob para estar en el estado $|1\\rangle$, entonces una sola medición podría resultar en $|1\\rangle.$. Realmente querríamos hacer muchas mediciones para estar seguros de que la probabilidad de $|0\\rangle$ es bastante alta.\n",
        "\n",
        "<span id=\"step-2-optimize-problem-for-quantum-execution\" />\n",
        "\n",
        "### Paso 2: Optimizar el problema para la ejecución cuántica\n",
        "\n",
        "Este paso toma las operaciones que queremos realizar y las expresa en términos de la funcionalidad de un ordenador cuántico específico. También mapea nuestro problema en el diseño del ordenador cuántico.\n",
        "\n",
        "Empezaremos cargando varios paquetes necesarios para comunicarnos con los ordenadores cuánticos de IBM. También debemos seleccionar 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/initialize-account) 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": "8f24b6b9-db1b-4077-8660-e355e377807e",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "ibm_sherbrooke\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": "35bb9c51-a573-4363-89ed-2159aaa1976f",
      "metadata": {},
      "source": [
        "Habilitamos explícitamente la lógica en las mediciones.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "e238e397-33f2-4fa1-99b1-94c78dd966f1",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.circuit import IfElseOp\n",
        "\n",
        "backend.target.add_instruction(IfElseOp, name=\"if_else\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6074a3b9-54c3-4c52-90ee-f308bd96de76",
      "metadata": {},
      "source": [
        "Ahora debemos \"transpilar\" el circuito cuántico. Esto implica muchos pasos secundarios y es un tema fascinante. Por poner un ejemplo de un subpaso: no todos los ordenadores cuánticos pueden implementar directamente todas las puertas lógicas de Qiskit. Debemos escribir las puertas de nuestro circuito en términos de puertas que el ordenador cuántico pueda implementar. Podemos llevar a cabo ese proceso, y otros, utilizando un gestor de pases preestablecido. La configuración de `optimization = 3` (el nivel más alto de optimización) garantiza que el mapeo de nuestro circuito cuántico abstracto a las instrucciones dadas al ordenador cuántico sea tan eficiente como pueda conseguirlo nuestro preprocesamiento.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "c533d4a7-c53c-4048-bf99-46e06ad9cb95",
      "metadata": {},
      "outputs": [],
      "source": [
        "# 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)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "85f3e53c-f910-4427-a977-f6e24798542c",
      "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": 9,
      "id": "d3292506-1486-48cd-bf1e-696135572eab",
      "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": "5ea27bf8-2dbf-4d68-8375-e40e89b71341",
      "metadata": {},
      "source": [
        "No todos los cálculos de un ordenador cuántico pueden simularse razonablemente en ordenadores clásicos. Este simple teletransporte sin duda puede serlo, pero no es en absoluto sorprendente que podamos guardar clásicamente información en un lugar u otro. Recomendamos encarecidamente realizar estos cálculos con un ordenador cuántico real IBM. Pero en caso de que haya agotado su uso mensual gratuito, o si algo debe completarse en clase y no puede esperar en la cola, este módulo puede completarse utilizando un simulador. Para ello, basta con ejecutar la celda siguiente y descomentar las líneas asociadas en los pasos \"Ejecutar\".\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "2332b984-cff6-4022-b7fa-f100d35a2719",
      "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",
        "\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": "bff5bb04-fc2d-45f4-ab26-98fe9a5a0b5c",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute\" />\n",
        "\n",
        "### Paso 3: Ejecutar\n",
        "\n",
        "Utilice el muestreador para ejecutar su trabajo, con el circuito como argumento.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "cbf63f9a-5b93-4bbd-b527-f3892e2188bd",
      "metadata": {},
      "outputs": [],
      "source": [
        "job = sampler.run([qc_isa])\n",
        "# job = sampler_sim.run([qc_isa])\n",
        "res = job.result()\n",
        "counts = res[0].data.c.get_counts()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a6a68d85-486a-401a-8336-805713eafd57",
      "metadata": {},
      "source": [
        "<span id=\"step-4-post-processing-and-analysis\" />\n",
        "\n",
        "### Paso 4: Posprocesamiento y análisis\n",
        "\n",
        "Vamos a trazar los resultados e interpretarlos.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "47488ddf-9357-41e4-a0fb-45616bee307c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/quantum-teleportation/extracted-outputs/47488ddf-9357-41e4-a0fb-45616bee307c-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# This required 5 s to run on a Heron r2 processor on 10-28-24\n",
        "from qiskit.visualization import plot_histogram\n",
        "\n",
        "plot_histogram(counts)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "12dcb4f6-d105-41f0-8800-87f291ce1aeb",
      "metadata": {},
      "source": [
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Comprueba tu comprensión\n",
        "\n",
        "¿Cuáles de los estados anteriores indican que el teletransporte se ha realizado con éxito, y cómo se puede saber?\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Respuesta\">\n",
        "    Los estados $|000\\rangle,$ $|001\\rangle,$ $|010\\rangle,$ $|011\\rangle$ son todos coherentes con el éxito del teletransporte. Esto se debe a que hemos añadido una puerta para deshacer la preparación inicial del estado secreto. Si el estado secreto fue teletransportado con éxito al qubit de Bob, esa puerta adicional debería devolver el qubit de Bob al estado $|0\\rangle$. Así que cualquier estado anterior con el qubit de Bob (qubit 0, también medido al componente 0 del registro clásico, y por tanto el más alto/más a la derecha) en el estado $|0\\rangle$ indica éxito.\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "Este gráfico muestra todos los resultados de las mediciones de los tres qubits, a lo largo de 5.000 ensayos o \"disparos\". Antes hemos señalado que Alice mediría todos los estados posibles de los qubits A y Q con la misma probabilidad. Asignamos los qubits 0-2 del circuito a Q, A y B, en ese orden. En notación little-endian, el qubit de Bob es el más a la izquierda/más bajo. Así, las cuatro barras de la izquierda corresponden a que el qubit de Bob es $|0\\rangle$, y los otros dos qubits están en todas las combinaciones posibles con una probabilidad aproximadamente igual. Nótese que casi todas las mediciones (normalmente \\~95%) muestran el qubit de Bob en el estado $|0\\rangle$, ¡lo que significa que nuestra configuración ha sido un éxito! Hay un puñado de disparos (\\~5%) que produjeron el qubit de Bob en el estado $|1\\rangle$. Lógicamente, eso no debería ser posible. Sin embargo, todos los ordenadores cuánticos modernos sufren ruido y errores en mucha mayor medida que los ordenadores clásicos. Y la corrección cuántica de errores sigue siendo un campo emergente.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cd75b04b-2d2d-4d87-b6cc-b0fed440d912",
      "metadata": {},
      "source": [
        "<span id=\"experiment-2-teleporting-across-a-processor\" />\n",
        "\n",
        "## Experimento 2: Teletransportación a través de un procesador\n",
        "\n",
        "Podría decirse que lo más interesante del teletransporte cuántico es que un estado cuántico puede teletransportarse a grandes distancias de forma instantánea (aunque la comunicación clásica de puertas adicionales no es instantánea). Como ya se ha dicho, no podemos separar los qubits del procesador y moverlos. Pero podemos mover la información de un qubit a otro, hasta que los qubits implicados en el teletransporte estén en lados opuestos del procesador. Repitamos los pasos anteriores, pero ahora haremos un circuito más grande con suficientes qubits para abarcar todo el procesador.\n",
        "\n",
        "<span id=\"step-1-map-your-problem-to-a-quantum-circuit\" />\n",
        "\n",
        "### Paso 1: Asigne su problema a un circuito cuántico\n",
        "\n",
        "Esta vez, los qubits correspondientes a Alice y Bob cambiarán. Por tanto, no llamaremos \"A\" a un qubit y \"B\" a otro. En su lugar, numeraremos los qubits y utilizaremos variables para representar la posición actual de la información en los qubits pertenecientes a Alice y Bob. Todos los demás pasos, excepto las puertas de intercambio, son como los descritos anteriormente.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "7d7742fa-e9a2-4ca0-9d9b-f29d73e07cd9",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/quantum-teleportation/extracted-outputs/7d7742fa-e9a2-4ca0-9d9b-f29d73e07cd9-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Step 1: Map\n",
        "\n",
        "# Define registers\n",
        "qr = QuantumRegister(13, \"q\")\n",
        "\n",
        "qc = QuantumCircuit(qr, cr)\n",
        "\n",
        "# Define registers\n",
        "secret = QuantumRegister(1, \"Q\")\n",
        "ebitsa = QuantumRegister(6, \"A\")\n",
        "ebitsb = QuantumRegister(6, \"B\")\n",
        "# q = ClassicalRegister(1, \"q meas\")\n",
        "# a = ClassicalRegister(1, \"a\")\n",
        "# b = ClassicalRegister(1, \"b\")\n",
        "cr = ClassicalRegister(3, \"c\")\n",
        "qc = QuantumCircuit(secret, ebitsa, ebitsb, cr)\n",
        "\n",
        "# We'll start Alice in the middle of the circuit, then move information outward in both directions.\n",
        "Alice = 5\n",
        "Bob = 0\n",
        "qc.h(ebitsa[Alice])\n",
        "qc.cx(ebitsa[Alice], ebitsb[Bob])\n",
        "\n",
        "# Starting with Bob and Alice in the center, we swap their information onto adjacent qubits,\n",
        "# until the information is on distant qubits.\n",
        "\n",
        "for n in range(Alice):\n",
        "    qc.swap(ebitsb[Bob], ebitsb[Bob + 1])\n",
        "    qc.swap(ebitsa[Alice], ebitsa[Alice - 1])\n",
        "    Alice = Alice - 1\n",
        "    Bob = Bob + 1\n",
        "\n",
        "qc.barrier()\n",
        "\n",
        "# Create a random state for Alice (qubit zero)\n",
        "np.random.seed(42)  # fixing seed for repeatability\n",
        "# theta = np.random.uniform(0.0, 1.0) * np.pi    #from 0 to pi\n",
        "theta = 0.3\n",
        "varphi = np.random.uniform(0.0, 2.0) * np.pi  # from 0 to 2*pi\n",
        "\n",
        "\n",
        "qc.u(theta, varphi, 0.0, secret)\n",
        "\n",
        "# Entangle Alice's two qubits\n",
        "qc.cx(secret, ebitsa[Alice])\n",
        "qc.h(secret)\n",
        "\n",
        "qc.barrier()\n",
        "\n",
        "# Make measurements of Alice's qubits and store the results in the classical register.\n",
        "qc.measure(ebitsa[Alice], cr[1])\n",
        "qc.measure(secret, cr[0])\n",
        "\n",
        "# Send instructions to Bob's qubits based on the outcome of Alice's measurements.\n",
        "with qc.if_test((cr[1], 1)):\n",
        "    qc.x(ebitsb[Bob])\n",
        "with qc.if_test((cr[0], 1)):\n",
        "    qc.z(ebitsb[Bob])\n",
        "\n",
        "qc.barrier()\n",
        "\n",
        "# Invert the preparation we did for Carl's qubit so we can check whether we did this correctly.\n",
        "qc.u(theta, varphi, 0.0, ebitsb[Bob]).inverse()  # inverse of u(theta,varphi,0.0)\n",
        "qc.measure(ebitsb[Bob], cr[2])  # add measurement gate\n",
        "\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5174ffeb-28d4-49d4-9693-5271e026b026",
      "metadata": {},
      "source": [
        "Puedes ver en el diagrama del circuito que los pasos lógicos son los mismos. La única diferencia es que usamos las puertas de intercambio para llevar el estado del qubit de Alice desde el qubit 6 ( $A_5$ ) hasta el qubit 1 ( $A_0$ ), justo al lado de Q. Y usamos puertas de intercambio para llevar el estado inicial de Bob desde el qubit 7 ( $B_0$ ) hasta el qubit 12 ( $B_5$ ). Nótese que el estado en el qubit 12 ni siquiera está relacionado con el estado secreto de Q hasta que se hacen mediciones en los qubits distantes 0 y 1, y el estado en el qubit 12 no es igual al estado secreto hasta después de que se aplican las puertas condicionales $X$ y $Z$.\n",
        "\n",
        "<span id=\"step-2-optimize-your-circuit\" />\n",
        "\n",
        "### Paso 2: Optimiza tu circuito\n",
        "\n",
        "Normalmente, cuando utilizamos el gestor de pasadas para transpilar y optimizar nuestros circuitos, tiene sentido configurar `optimization_level = 3`, porque queremos que nuestros circuitos sean lo más eficientes posible. En este caso, no hay ninguna razón computacional para que transfiramos los estados de los qubits 6 y 7 a los qubits 1 y 12. Eso fue sólo algo que hicimos para demostrar el teletransporte a distancia. Si le pedimos al gestor de pases que optimice nuestro circuito, se dará cuenta de que no hay ninguna razón lógica para estas puertas de intercambio, las eliminará y realizará las operaciones de puerta en qubits adyacentes. Así que para este caso especial, utilizamos `optimization_level = 0`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "d7865560-a8a6-4abb-af8d-6a86ecc76bff",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "105\n"
          ]
        }
      ],
      "source": [
        "# Step 2: Transpile\n",
        "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
        "\n",
        "target = backend.target\n",
        "pmzero = generate_preset_pass_manager(target=target, optimization_level=0)\n",
        "\n",
        "qc_isa_zero = pmzero.run(qc)\n",
        "\n",
        "print(qc_isa_zero.depth())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "38c1dc99-e5e0-4969-b7a0-cdc1e4e6bedd",
      "metadata": {},
      "source": [
        "Podemos visualizar en qué parte del procesador cuántico se encuentran estos qubits utilizando la función `plot_circuit_layout` .\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6a74e5a5-d32f-41a5-adf8-29174a0d5e8a",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute\" />\n",
        "\n",
        "### Paso 3: Ejecutar\n",
        "\n",
        "Como antes, recomendamos ejecutar en ordenadores cuánticos reales IBM. Si ha alcanzado su consumo mensual gratuito, no dude en descomentar las celdas del simulador para ejecutarlas en un simulador.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "5536d98a-480b-4193-8c63-2ef77d1aeda0",
      "metadata": {},
      "outputs": [],
      "source": [
        "# This required 5 s to run on a Heron r2 processor on 10-28-24\n",
        "job = sampler.run([qc_isa_zero])\n",
        "# job = sampler_sim.run([qc_isa_zero])\n",
        "counts = job.result()[0].data.c.get_counts()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "13b6375b-73c7-436d-bf1c-98de45ef4056",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/quantum-teleportation/extracted-outputs/13b6375b-73c7-436d-bf1c-98de45ef4056-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 16,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.visualization import plot_histogram\n",
        "\n",
        "plot_histogram(counts)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "49ed3ba0-3482-4ad5-84c3-f8fba80d8668",
      "metadata": {},
      "source": [
        "<span id=\"step-4-classical-post-processing\" />\n",
        "\n",
        "### Paso 4: Postprocesamiento clásico\n",
        "\n",
        "De nuevo vemos que las probabilidades de los posibles resultados de los qubits de Alice son bastante uniformes. Hay una fuerte preferencia por encontrar el qubit de Bob en $|0\\rangle$ después de invertir el código secreto, lo que significa que hay una fuerte probabilidad de que hayamos teletransportado correctamente el estado secreto a través del procesador de Q a Bob (qubits 0 a 12). Sin embargo, observamos que ahora hay aproximadamente una mayor probabilidad de *no* medir $|0\\rangle$ para Bob. Ésta es una lección importante en computación cuántica: cuantas más puertas se tengan, especialmente puertas multi-qubit como las puertas de intercambio, más ruido y errores se encontrarán.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ede2724d-536b-472a-b4bd-b1276b5b851d",
      "metadata": {},
      "source": [
        "<span id=\"questions\" />\n",
        "\n",
        "## Preguntas\n",
        "\n",
        "Los instructores pueden solicitar versiones de estos cuadernos con claves de respuestas y orientación sobre la colocación en planes de estudios comunes rellenando esta [rápida encuesta](https://ibm.biz/classrooms_instructor_key_request) sobre cómo se están utilizando los cuadernos.\n",
        "\n",
        "<span id=\"critical-concepts\" />\n",
        "\n",
        "### Conceptos fundamentales\n",
        "\n",
        "* Los qubits pueden estar entrelazados, lo que significa que la medición de un qubit afecta o incluso determina el estado de otro qubit.\n",
        "* El entrelazamiento difiere de las correlaciones clásicas; por ejemplo, los qubits A y B podrían estar en una superposición de estados como $\\alpha_0|00\\rangle+\\alpha_1|11\\rangle.$. El estado de A o B podría ser indeterminado por la naturaleza, y aun así podría garantizarse que A y B se encuentran en el mismo estado.\n",
        "* Mediante una combinación de entrelazamientos y mediciones, podemos transferir un estado (que puede almacenar información) de un qubit a otro. Esta transferencia puede realizarse incluso a grandes distancias, lo que se denomina teletransporte cuántico.\n",
        "* El teletransporte cuántico se basa en mediciones cuánticas, que son probabilísticas. Así, la comunicación clásica puede ser necesaria para modificar los estados teletransportados. Esto impide que el teletransporte cuántico mueva la información más rápido que la luz. El teletransporte cuántico no viola la relatividad ni la causalidad.\n",
        "* Los ordenadores cuánticos modernos son más susceptibles al ruido y a los errores que los clásicos. Espere un pequeño porcentaje de error.\n",
        "* Cuantas más puertas se añadan en secuencia (especialmente puertas de 2 qubits), más errores y ruido cabe esperar.\n",
        "\n",
        "<span id=\"true/false-questions\" />\n",
        "\n",
        "### Preguntas de verdadero/falso\n",
        "\n",
        "1. T/F El teletransporte cuántico puede utilizarse para enviar información más rápido que la luz.\n",
        "2. T/F La evidencia moderna sugiere que el colapso de un estado cuántico se propaga más rápido que la luz.\n",
        "3. T/F En Qiskit, los qubits se ordenan en estados con el qubit de menor número a la derecha, como en $|q_3,q_2,q_1, q_0\\rangle$\n",
        "\n",
        "<span id=\"mc-questions\" />\n",
        "\n",
        "### Preguntas del maestro de ceremonias\n",
        "\n",
        "1. Los qubits A y B están entrelazados y separados por una gran distancia $d$. Se mide el Qubit A. ¿Qué afirmación es correcta sobre la velocidad a la que se ve afectado el estado del qubit B?\n",
        "\n",
        "* a. El Qubit B se ve afectado instantáneamente, dentro de la tolerancia experimental, en los experimentos realizados hasta ahora.\n",
        "* b. El Qubit B se ve afectado al cabo de un tiempo $d/c$, lo que significa que el estado cuántico \"colapsa\" aproximadamente a la velocidad de la luz, dentro de la tolerancia experimental.\n",
        "* c. El Qubit B sólo se ve afectado después de que se haya producido la comunicación clásica, es decir, en un tiempo superior a $d/c$.\n",
        "* d. Ninguno de los anteriores\n",
        "\n",
        "2. Recordemos que la probabilidad de medición está relacionada con las amplitudes de los estados cuánticos. Por ejemplo, si un qubit se encuentra inicialmente en el estado $\\alpha_0|0\\rangle+\\alpha_1 |1\\rangle,$, la probabilidad de medir el estado $|0\\rangle$ es $|\\alpha_0|^2.$. No todos los conjuntos de mediciones coincidirán exactamente con estas probabilidades, debido al muestreo finito (del mismo modo que lanzar una moneda puede dar cara dos veces seguidas). El histograma de medida que se muestra a continuación, ¿a cuál de los siguientes estados cuánticos podría corresponder? Seleccione la mejor opción.\n",
        "\n",
        "![entangled\\_teleportation\\_fig](https://quantum.cloud.ibm.com/learning/images/modules/computer-science/quantum-teleportation/entangled_teleportation_fig.avif)\n",
        "\n",
        "* a. $|0\\rangle$\n",
        "* b. $\\frac{1}{\\sqrt{2}}\\left(|0\\rangle-|1\\rangle\\right)$\n",
        "* c. $\\frac{1}{\\sqrt{2}}\\left(|0\\rangle+|1\\rangle\\right)$\n",
        "* d. $\\frac{4}{5}|0\\rangle+\\frac{3}{5}|1\\rangle$\n",
        "* e. $\\frac{3}{5}|0\\rangle+\\frac{4}{5}|1\\rangle$\n",
        "\n",
        "3. ¿Cuál(es) de los siguientes estados muestra(n) los qubits A y B entrelazados? Seleccione todo lo que corresponda\n",
        "\n",
        "* a. $\\frac{1}{\\sqrt{2}}\\left(|0\\rangle_B|0\\rangle_A+|1\\rangle_B|1\\rangle_A\\right)$\n",
        "* b. $\\frac{4}{5}|0\\rangle_B|0\\rangle_A+\\frac{3}{5}|1\\rangle_B|1\\rangle_A$\n",
        "* c. $\\frac{1}{\\sqrt{2}}\\left(|0\\rangle_B|1\\rangle_A-|1\\rangle_B|0\\rangle_A\\right)$\n",
        "* d. $\\frac{1}{\\sqrt{2}}\\left(|0\\rangle_B|0\\rangle_A+|1\\rangle_B|0\\rangle_A\\right)$\n",
        "* e. $|0\\rangle_B|0\\rangle_A$\n",
        "\n",
        "4. En este módulo hemos preparado un estado entrelazado: $\\frac{1}{\\sqrt{2}}\\left(|0\\rangle_B|0\\rangle_A+|1\\rangle_B|1\\rangle_A\\right).$ Pero hay muchos otros estados enredados que se podrían utilizar para un protocolo similar. ¿Cuál de los siguientes estados podría dar lugar a un histograma de medidas de 2 qubits como el siguiente? Seleccione la mejor respuesta.\n",
        "\n",
        "![entangled\\_teleportation\\_fig\\_0110](https://quantum.cloud.ibm.com/learning/images/modules/computer-science/quantum-teleportation/entangled_teleportation_fig_0110.avif)\n",
        "\n",
        "* a. $\\frac{1}{\\sqrt{2}}\\left(|0\\rangle_B|0\\rangle_A+|1\\rangle_B|1\\rangle_A\\right)$\n",
        "* b. $\\frac{4}{5}|0\\rangle_B|0\\rangle_A+\\frac{3}{5}|1\\rangle_B|1\\rangle_A$\n",
        "* c. $\\frac{1}{\\sqrt{2}}\\left(|0\\rangle_B|1\\rangle_A-|1\\rangle_B|0\\rangle_A\\right)$\n",
        "* d. $\\frac{4}{5}|0\\rangle_B|1\\rangle_A+\\frac{3}{5}|1\\rangle_B|0\\rangle_A$\n",
        "* e. $|0\\rangle_B|0\\rangle_A$\n",
        "\n",
        "<span id=\"discussion-questions\" />\n",
        "\n",
        "### Preguntas para el debate\n",
        "\n",
        "1. Describe el protocolo de teletransporte cuántico, de principio a fin, a tu compañero/grupo. A ver si tienen algo que añadir o si tienen preguntas.\n",
        "\n",
        "2. ¿Hay algo único en el estado inicial entrelazado entre Alice y Bob? $\\frac{1}{\\sqrt{2}}\\left(|0\\rangle_B|0\\rangle_A+|1\\rangle_B|1\\rangle_A\\right)?$ Si es así, ¿qué tiene de único? Si no, ¿qué otros estados entrelazados podríamos haber utilizado?\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": 4
}