{ "cells": [ { "cell_type": "markdown", "id": "b893110e-1835-4b67-bfd9-5b9402840c2a", "metadata": {}, "source": [ "(algrebralineal)=\n", "# Introducción. Álgebra\n", "\n", "```{index} statevector, vector de estado\n", "```\n", "En este apartado vamos a ver diferentes forma de representar los qubits. Seguiremos trabajando, de momento, con un sólo qubit y presentaremos diferentes operaciones sobre ellos. Comprenderemos lo que es el producto interno y ciertas propiedades sobre el mismo.\n", "\n", "Veamos en primer cómo poder representar mediante coordenada los qubits de la base $\\{|0\\rangle , |1\\rangle \\}$.\n", "\n", "$$|0\\rangle={\\binom{1}{0}},\\quad|1\\rangle={\\binom{0}{1}}.$$\n", "\n", "Como podemos ver se han utilizado vectores columnas para representar estos vectores que vamos a denominar *statevector* o *vectores de estado*.\n", "\n", "De la misma manera se podría representar cualquier qubit que tuviera de amplitudes $\\alpha$ y $\\beta$. Es decir se tendría la siguiente representación:\n", "\n", "$$|\\psi\\rangle=\\alpha|0\\rangle+\\beta|1\\rangle=\\alpha\\binom{1}{0}+\\beta\\binom{0}{1}={\\binom{\\alpha}{0}}+{\\binom{0}{\\beta}}=$$\n", "$$={\\binom{\\alpha}{\\beta}}.$$\n", "\n", "Como ya sabemos los qubits $\\{|i\\rangle, |-i\\rangle\\} forman una base por lo tanto el qubit $|i\\rangle$ se puede representar por el siguiente vector columna en esa base:\n", "\n", "$$\\left(\\begin{array}{c}\n", "1\\\\\n", "0\n", "\\end{array}\\right)$$\n", "\n", "Pero en la base formada por los qubits $|0\\rangle$ y $|1\\rangle$ ( que en adelante la llamaremos la base canónica), su expresión sería de las siguiente manera:\n" ] }, { "cell_type": "markdown", "id": "a9b0d2df-ddbe-4c9c-aa54-2c4fa1f663eb", "metadata": {}, "source": [ "$$|i\\rangle=\\frac{1}{\\sqrt{2}}|0\\rangle+\\frac{i}{\\sqrt{2}}|1\\rangle=\\frac{1}{\\sqrt{2}}{\\binom{1}{0}}+\\frac{i}{\\sqrt{2}}{\\binom{0}{1}}={\\binom{1/{\\sqrt{2}}}{0}}+{\\binom{0}{i/{\\sqrt{2}}}}=$$\n", "$$={\\binom{1/{\\sqrt{2}}}{i/{\\sqrt{2}}}}={\\frac{1}{\\sqrt{2}}}{\\binom{1}{i}}.$$\n", "\n", "Igualmente sabemos que $H(|0\\rangle)=|+\\rangle=\\frac{1}{\\sqrt{2}}\\left(|0\\rangle+|1\\rangle\\right)$, por lo que en este caso el vector columna será:\n", "\n", "$$\\binom{\\frac{1}{\\sqrt{2}}}{\\frac{1}{\\sqrt{2}}}$$" ] }, { "cell_type": "markdown", "id": "ecff47f4-4c5c-4a5e-8f1b-e0686deb3b2c", "metadata": {}, "source": [ "En el mundo de la programación cuántica, este tipo de vectores se denominan [*statevector* o *vectores de estado*](statevector), qiskit tiene una clase específicamente diseñada para trabajar con este tipo de elementos. A continuación veamos cómo introducir esta clase.\n", "\n", "La forma de definir un vector de estado sería de la siguiente manera: " ] }, { "cell_type": "code", "execution_count": 1, "id": "8f7455df-796e-4b44-8f10-8fdc130c402b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "El vector de estado generado es el siguiente: Statevector([1.+0.j, 0.+0.j],\n", " dims=(2,))\n" ] } ], "source": [ "from qiskit.quantum_info import Statevector\n", "v1=Statevector([1,0])\n", "print(\"El vector de estado generado es el siguiente: \", v1)" ] }, { "cell_type": "markdown", "id": "a573cf1f-a251-45c6-b8aa-911465944ddf", "metadata": {}, "source": [ "En el ejemplo anterior, la forma de definir ese vector de estado sería la siguiente:\n" ] }, { "cell_type": "code", "execution_count": 2, "id": "6931300a-3be8-49bb-a1a3-af1b48280037", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Statevector([0.70710678+0.j , 0. +0.70710678j],\n", " dims=(2,))\n" ] } ], "source": [ "import numpy as np\n", "v2 = Statevector([(1/np.sqrt(2))+0j,0+1j*(1/np.sqrt(2))])\n", "print(v2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Igualmente ya hemos dicho que se cumple lo siguiente: $H(|0\\rangle)=|+\\rangle=\\frac{1}{\\sqrt{2}}\\left(|0\\rangle+|1\\rangle\\right)$, por lo que en este caso el vector columna será:\n", "\n", "$$\\binom{\\frac{1}{\\sqrt{2}}}{\\frac{1}{\\sqrt{2}}}$$\n", "\n", "Veamos que con quiskit también podemos obtener este resultado, y para ello definimos un circuito de un sólo qubit al que se le aplica una puerta H\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Statevector([0.707+0.j, 0.707+0.j],\n", " dims=(2,))\n" ] } ], "source": [ "from qiskit import QuantumCircuit\n", "# Definimos el circuito de un solo qubit\n", "circuito = QuantumCircuit(1)\n", "\n", "#Aplicamos un puerta H\n", "circuito.h(0)\n", "\n", "# Import Aer\n", "from qiskit import Aer\n", "\n", "# Ejecutamos el circuito sobre un simulador de statevector simulator backend\n", "backend = Aer.get_backend('statevector_simulator')\n", "\n", "# creamos un programa cuántico para ejecución.\n", "job = backend.run(circuito)\n", "\n", "# obtenemos el resultado\n", "result = job.result()\n", "\n", "# Ahora ya podemos sacar el vector de estado y lo imprimimos\n", "outputstate = result.get_statevector(circuito, decimals=3)\n", "print(outputstate)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.7071067811865475\n" ] } ], "source": [ "# Comprobamos que el resultado es el correcto\n", "print(1/np.sqrt(2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Vectores fila.\n", "```{index} bra-ket (notation)\n", "```\n", "Los vectores fila, no son más que el vector columna transpuesto, es decir :\n", "\n", "$$\\binom{\\alpha}{\\beta}^{T}=\\left(\\alpha,\\beta\\right)$$\n", "\n", "Sin embargo en la programación cuántica, se utiliza mucho el denominado vector transpuesto conjugado, que como su nombre indica consiste en tomar el vector transpuesto y después el conjugado. Se denota por el superíndice $\\dagger$:\n", "\n", "$${\\binom{\\alpha}{\\beta}}^{\\dagger}=(\\alpha^{*}\\,\\beta^{*}).$$\n", "\n", "De acuerdo con esta explicación, también hay que comentar que dentro de la programación cuántica se utiliza mucho la notación *bra-ket*. La parte ket ya se ha utilizado anteriormente y por y un ejemplo de la misma puede ser: $|1\\rangle$, sin embargo, con la parta bra, queremos indicar lo siguiente:\n", "\n", "$$\\langle\\psi|=(\\alpha^{*}\\,\\beta^{*}).$$\n", "\n", "## El producto interno.\n", "\n", "Así pues y tal como se ha presentado en el anterior apartado, la parte *bra* no es más que el transpuesto conjugado de la parte *bra*. Por ejemplo, vamos a considerar un qubit ya utilizado anteriormente en este capítulo:\n", "\n", "$$|i\\rangle={\\binom{1/{\\sqrt{2}}}{i/{\\sqrt{2}}}}={\\frac{1}{\\sqrt{2}}}{\\binom{1}{i}}.$$\n", "\n", "Por lo tanto la parte bra de la expresión anterior, sería la siguiente:\n", "\n", "$$|i\\rangle=(1/{\\sqrt{2}},-i/{\\sqrt{2}})$$\n", "\n", "Podemos tomar los transpuestos conjugados de $|0\\rangle=\\binom{1}{0}$ y $|1\\rangle=\\binom{0}{1}$, tiene las siguientes partes bra:\n", "\n", "$$\\langle 0| = (1 , 0) \\quad \\langle1|=(0 , 1)$$\n", "\n", "Y entonces podemos tener la siguiente conclusión:\n", "\n", "$$\\begin{array}{c}{{\\langle\\psi|=(\\alpha^{\\ast}\\beta^{\\ast})=(\\alpha^{\\ast}\\ 0)+(0\\,\\beta^{\\ast})=\\alpha^{\\ast}(1\\ 0)+\\beta^{\\ast}(0\\ 1)}}\\\\ {{=\\alpha^{\\ast}\\langle0|+\\beta^{\\ast}\\langle1|.}}\\end{array}$$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notemos que en este caso tendremos amplitudes $\\alpha^*$ y $\\beta^*$ y por lo tanto cuando pasamos de $|\\psi\\rangle$ a $\\langle \\psi|$, lo que se necesita es tomar los complejos conjugados de las amplitudes y pasar de vector columna a vector fila. Por ejemplo, si sabemos que $|i\\rangle=\\frac{1}{\\sqrt{2}}|0\\rangle+\\frac{i}{\\sqrt{2}}|1\\rangle$, entonces:\n", "\n", "$$\\langle i|=\\frac{1}{\\sqrt{2}}\\langle0|-\\frac{i}{\\sqrt{2}}\\langle1|$$\n", "\n", "Resumamos todo esto a continuación\n", "\n", "$$|\\Psi\\rangle={\\binom{\\alpha}{\\beta}}\\Longleftrightarrow\\quad\\quad\\langle\\Psi|=(\\alpha^{*}\\,{\\beta^{*}})$$\n", "\n", "$$|\\psi\\rangle=\\alpha|0\\rangle+\\beta|1\\rangle\\iff\\langle\\psi|=\\alpha^{*}\\langle0|+\\beta^{*}\\langle1|$$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "(productointerno)=\n", "## Productos internos o escalar.\n", "\n", "Supongamos que tenemos dos estados:\n", "\n", "$$|\\Psi\\rangle={\\binom{\\alpha}{\\beta}},\\quad y \\quad|\\phi\\rangle={\\binom{\\gamma}{\\delta}}$$\n", "\n", "Definiremos su producto interno y lo designaremos por $\\langle \\Psi | \\phi\\rangle$, de la siguiente manera:\n", "\n", "$$\\langle\\Psi|\\phi\\rangle=\\left(\\alpha^{*}\\,\\beta^{*}\\right)\\left(\\gamma, \\delta\\right) $$\n", "\n", "El resultado por lo tanto será un escalar complejo, y en concreto:\n", "\n", "$$ \\langle\\phi|\\psi\\rangle=\\alpha^{*}\\gamma+\\beta^{*}\\delta.$$\n", "\n", "Una propiedad muy importante del producto escalar es que el producto escalar de $\\Psi$ y $\\phi$ es igual cl complejo del producto escalar de $\\phi$ por $\\Psi$. Es decir:\n", "\n", "$$\\langle\\Psi|\\phi\\rangle=\\langle\\phi|\\Psi\\rangle^{*}$$\n", "\n", "Un conclusión del resultado anterior es que el producto interno no tiene la propiedad conmutativa.\n", "\n", "Vamos a demostrar el enunciado anterior.\n", "\n", "$$\\begin{array}{c}{{\\langle\\Psi|\\phi\\rangle=(\\gamma^{*}\\;\\delta^{*})\\binom{\\alpha}{\\beta}=\\gamma^{*}\\alpha+\\delta^{*}\\beta=(\\gamma\\alpha^{*}+\\delta\\beta^{*})^{*}=(\\alpha^{*}\\gamma+\\beta^{*}\\delta)^{*}}}\\\\ {{=\\langle\\phi\\left|\\Psi\\right\\rangle^{*}.}}\\end{array}$$\n", "\n", "Veamos cómo calcular el producto interno desde quiskit. Supongamos que tenemos los siguientes qubits.\n", "\n", "$$|a\\rangle=\\frac{3+i\\sqrt{3}}{4}|0\\rangle+\\frac{1}{2}|1\\rangle$$\n", "\n", "$$|b\\rangle=\\frac{1}{4}|0\\rangle+\\frac{\\sqrt{15}}{4}|1\\rangle$$\n", "\n", "Procedamos al cálculo del producto interno con qiskit\n" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "El producto interno es: \n" ] }, { "data": { "text/plain": [ "(0.6716229182759271-0.10825317547305482j)" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from qiskit.quantum_info import Statevector\n", "import numpy as np\n", "# definimos el primer vector de estado\n", "v1 = Statevector([3/4+1j*(np.sqrt(3)/4),1/2])\n", "v2 = Statevector([1/4,np.sqrt(15)/4])\n", "\n", "# Ahora calculamos el producto interno\n", "print(\"El producto interno es: \")\n", "v1.inner(v2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ortonormalidad.\n", "\n", "Una vez introducido el concepto de producto interno, vamos a ver que nos podemos apoyar en él para demostrar ciertas condiciones que ya sabemos deben cumplirse al trabajar con qubits.\n", "\n", "En este sentido, supongamos que tenemos el siguiente qubit: $\\Psi = \\alpha |0\\rangle +\\beta |1\\rangle$, como es un qubit debe estar sobre la esfera de radio unidad, y por lo tanto verifica que $|\\alpha|^2+|\\beta|^2 =1$. Pero vemos cunato vale el producto interno de ese qubit consigo mismo:\n", "\n", "$$\\langle\\Psi|\\Psi\\rangle=(\\alpha^{*},\\beta^{*})\\binom{\\alpha}{\\beta}=|\\alpha|^{2}+|\\beta|^{2}=1$$\n", "\n", "Por lo tanto una condición que debe cumplir cada elemento de una base (que esté en la esfera de radio unidad), es que el producto interno del qubit por sí mismo es la unidad.\n", "\n", "Otra de las condiciones que deben cumplir los dos qubits que formen una base es que sean ortonormales. Veamos que esto es cierto para la base canónica.\n", "\n", "$$\\langle0|1\\rangle=\\left(1~0\\right)\\!\\left(_{1}^{0}\\right)=1\\cdot0+0\\cdot1=0+0=0$$\n", "\n", "Igual ocurre con los qubits $|+\\rangle$ y $|-\\rangle$\n", "\n", "$$\\left|+\\right\\rangle\\langle-|={\\frac{1}{\\sqrt2}}\\big(1\\left.1\\right){\\frac{1}{\\sqrt2}}\\binom{1}{-1}={\\frac{1}{2}}\\big(1\\ 1\\big)\\binom{1}{-1}={\\frac{1}{2}}\\left(1-1\\right)=0$$\n", "\n", "Lo mismo tenemos para los estados $|i\\rangle$ y $|-i\\rangle$:\n", "\n", "$$\\vert i\\rangle\\langle-i\\vert=\\frac{1}{\\sqrt{2}}(1-i)\\frac{1}{\\sqrt{2}}{\\binom{1}{-i}}=\\frac{1}{2}\\left(1-i\\right){\\binom{1}{-i}}=\\frac{1}{2}\\left(1+i^{2}\\right)=0$$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Siempre se va a verificar que dos puntos de la esfera de Bloch que estén en posiciones opuestas, siempre su producto interno va a ser cero, y estos dos puntos en esas condiciones, diremos que son ortogonales. Si además los dos puntos están normalizados, diremos que son ortonormales.\n", "\n", "(proyecciones)=\n", "## Proyecciones, medidas y cambios de base.\n", "\n", "El producto interno tiene muchas aplicaciones dentro de la programación cuántica, y alguna de ellas las vamos a ver en este apartado. En concreto vamos a ver cómo podemos utilizar este producto interno o escalar para medir amplitudes de estados cuánticos. Igualmente vamos a ver cómo proceder para hacer diferentes cambios de base. Para los propósitos de este apartado, vamos a trabajar con el siguiente qubit:\n", "\n", "$$|\\psi\\rangle={\\frac{\\sqrt{3}}{2}}|0\\rangle+{\\frac{1}{2}}|1\\rangle$$\n", "\n", "Este qubit ya [fue presentado en un apartado anterior](puntoesfera), y podemos decir que su representación gráfica sobre la esfera de Bloch es la siguiente:\n", "\n", "