martes, 28 de marzo de 2017

Algoritmos

Algoritmos cuánticos

algoritmo de Deutsch-Jozsa es un algoritmo cuántico, propuesto por David Deutsch y Richard Jozsa en 1992. Fue uno de los primeros algoritmos diseñados para ejecutar sobre un computador cuántico y que tiene el potencial de ser más eficiente que los algoritmos clásicos al aprovechar el paralelismo inherente de los estados de superposición cuánticos.
En el problema de Deutsch-Jozsa nos dan una función cuántica (que para nosotros es una caja negra) f(x1, x2,..., xn) que toma n bits de entrada x1, x2,..., xn y devuelve un valor binario f(x1, x2,..., xn). Sabemos que la función es constante (0 en todas las entradas o 1 en todas las entradas) o balanceada (devuelve 1 para la mitad de las entradas y 0 para la otra mitad); el problema es entonces determinar cómo es la función (constante o balanceada) aplicando entradas a la caja negra y observando su salida.

Algoritmo de Deutsch

Circuito cuántico que implementa el algoritmo de Deutsch.
Esta es una versión del algoritmo para una función f(x) de una sola entrada. Se utilizan dos qubits auxiliares en los cálculos. El algoritmo se ilustra en la figura de la derecha.
El bloque H es una puerta Hadamard cuya operación es la siguiente:
El bloque Uf realiza la operación siguiente:
Además,
La entrada al circuito es: , que atraviesa dos puestas Hardamard (véase la figura) obteniéndose . Esto atraviesa el bloque Uf obteneniéndose
Esta expresión puede escribirse:
Al atravesar la última puerta de Hadamard obtenemos:
Puesto que si  y si , podemos escribir
Este es el resultado final: midiendo el primer qubit de la ecuación obtenemos . Si resulta el valor 0, entonces la función f(x) es constante, mientras que si resulta 1, la función es balanceada.

Algoritmo de Deutsch-Jozsa

Circuito cuántico que implementa el algoritmo de Deutsch-Jozsa.
Esta es la versión general del algoritmo para funciones f(x) de n entradas.
En este caso, la entrada al circuito es:
A continuación de las puertas Hadamard se obtiene:
A la salida del bloque Uf se tiene:
La última puerta Hadamard produce la siguiente salida
Y por último, realizando la medición, se obtiene z. En el caso en que la función f(x) sea balanceda, las contribuciones para  se cancelan y la medida de z debe dar una combinación distinta. Por el contrario, si f(x) es constante se obtiene  en la medida, pues el resto de las contribuciones se cancelan en este caso. Por consiguiente, comprobando si z es cero o distinto de cero se sabe que la función es, respectivamente, constante o balanceada.

Algoritmo de Deutsch-Jozsa

Sea $V=\{0,1\}$ el conjunto de valores de verdad clásicos. De las $2^2=4$ funciones booleanas $f:V\to V$ dos son constantes y las otras dos son equilibradas. Al nombrarlas

\begin{displaymath}f_0:\begin{array}{ccc}
0 &\mapsto& 0 \\
1 &\mapsto& 0 %%\\
...
...n{array}{ccc}
0 &\mapsto& 1 \\
1 &\mapsto& 1 %%\\
\end{array}\end{displaymath}


se tiene que las funciones constantes son $f_0$ y $f_3$, y las equilibradas son $f_1$ y $f_2$.
El propósito del algoritmo de Deutsch-Jozsa es decidir, para una $f$ dada, si acaso es constante o equilibrada ``utilizando un solo paso de cómputo''.
Sea $U_f$ una matriz permutación de orden $2^{2}\times 2^{2}$ tal que $U_f(\mbox{\bf e}_{x}\otimes \mbox{\bf e}_{z})= (\mbox{\bf e}_{x}\otimes \mbox{\bf e}_{(z+f(x))\mbox{\scriptsize mod }2})$$U_f$ es pues unitaria. De hecho es muy similar al funcionamiento de la compuerta ``negación controlada'', salvo que en aquella, la función $f$ es propiamente la identidad. En la tabla 1 ilustramos la acción de $U_f$ refiriéndonos solamente a los índices de vectores básicos.

Recuadro 1: Acción de la matriz unitaria $U_f$ en el algoritmo de Deutsch-Jozsa.
$(x,z)$$(x,(z+f(x))\mbox{ mod }2)$
(0,0)(0,$f(0)$)
(0,1)(0, $\overline{f(0)}$)
(1,0)(1,$f(1)$)
(1,1)(1, $\overline{f(1)}$)


Considerando el operador de Hadamard $H$, hagamos $H_2=H\otimes H$. Primero se tiene, $H(\mbox{\bf e}_0) = \mbox{\bf x}_0=\frac{1}{\sqrt{2}}(\mbox{\bf e}_0+\mbox{\bf e}_1)$ y $H(\mbox{\bf e}_0) = \mbox{\bf x}_1=\frac{1}{\sqrt{2}}(\mbox{\bf e}_0-\mbox{\bf e}_1)\in\mathbb{H}_1$ y luego $H_2(\mbox{\bf e}_0\otimes \mbox{\bf e}_1) = H(\mbox{\bf e}_0)\otimes H(\mbox{\bf e}_1) = \mbox{\bf x}_0\otimes \mbox{\bf x}_1$. Claramente, $\mbox{\bf x}_0\otimes \mbox{\bf x}_1 = \frac{1}{2}(\mbox{\bf e}_{00}-\mbox{\bf e}_{01}+\mbox{\bf e}_{10}-\mbox{\bf e}_{11})\in\mathbb{H}_2.$ Por tanto,

\begin{eqnarray*}
U_f(\mbox{\bf x}_0\otimes \mbox{\bf x}_1) &=& \frac{1}{2}(\mbo...
...}_0\otimes \mbox{\bf x}_1 & \mbox{si } f=f_3
\end{array}\right.
\end{eqnarray*} 





En consecuencia,

\begin{eqnarray*}
H_2U_fH_2(\mbox{\bf e}_0\otimes \mbox{\bf e}_1) = H_2U_f(\mbox...
...}_0\otimes \mbox{\bf e}_1 & \mbox{si } f=f_3
\end{array}\right.
\end{eqnarray*} 





vale decir, al aplicar el algoritmo cuántico $H_2U_fH_2$ (nótese que utilizamos notación algebraica: los operadores se aplican de derecha a izquierda), partiendo del vector básico $\mbox{\bf e}_0\otimes \mbox{\bf e}_1$ se obtiene un vector de la forma $\varepsilon \mbox{\bf e}_S\otimes \mbox{\bf e}_1$ donde $\varepsilon\in\{-1,1\}$ es un signo y $S$ es una señal que indica si acaso $f$ es o no equilibrada. En otras palabras, la respuesta $S$ coincide con $f(0)\oplus f(1)$, donde $\oplus$ es la disyunción excluyenteXOR. La auscultación del valor $S$ se realiza siguiendo el postulado de medición, y su valor está apareciendo leyendo sólo el primer qubit. Al efectuar la medición se elige al vector básico $\mbox{\bf e}_S\otimes \mbox{\bf e}_1$ con probabilidad $\varepsilon^2=1$.





algoritmo de Grover es un algoritmo cuántico para la búsqueda en una secuencia no ordenada de datos con N componentes en un tiempo O (N1/2), y con una necesidad adicional de espacio de almacenamiento de O(logN) (véase notación O). Fue inventado por Lov K. Grover en 1996.
En una búsqueda normal de un dato, si tenemos una secuencia desordenada se debe realizar una inspección lineal, que necesita un tiempo de O (N), por lo que el algoritmo de Grover es una mejora bastante sustancial, evitando, además, la necesidad de la ordenación previa. La ganancia obtenida es "sólo" de la raíz cuadrada, lo que contrasta con otras mejoras de los algoritmos cuánticos que obtienen mejoras de orden exponencial sobre sus contrapartidas clásicas.
Al igual que otros algoritmos de naturaleza cuántica, el algoritmo de Grover es un algoritmo de carácter probabilístico, por lo que produce la respuesta correcta con una determinada probabilidad de error, que, no obstante, puede obtenerse tan baja como se desee por medio de iteraciones.

Aplicaciones

Aunque el propósito del algoritmo es, como ha sido indicado, la búsqueda en una secuencia, se podría describir de una manera más adecuada como la "inversión de una función". Así, si tenemos la función y=f (x), que puede ser evaluada en un computador cuántico, este algoritmo nos permite calcular el valor de x cuando se nos da como entrada el valor de y. Invertir una función puede relacionarse con la búsqueda en una secuencia, si consideramos que la misma es una función que produce el valor de y como la posición ocupada por el valor x en dicha secuencia.
El algoritmo de Grover también se puede utilizar para el cálculo de la media y la mediana de un conjunto de números, y para resolver otros problemas de naturaleza análoga. También se puede utilizar para resolver algunos problemas de naturaleza NP-completa, por medio de inspecciones exhaustivas en un espacio de posibles soluciones. Esto resulta en una apreciable mejora sobre soluciones clásicas.

Descripción

Inicialización

Se considera una secuencia desordenada con N componentes. El algoritmo requiere un espacio de estados N-dimensional H, que puede ser modelado con log2N qubits.
Numeremos las entradas de la secuencia con 0, 1,... (N-1); y seleccionemos un observable Ω, actuando sobre H, con N autovalores distintos conocidos. Cada uno de los autovalores de Ω codifica una de las entradas de la secuencia, de una forma que se describirá más adelante. Denotaremos los autoestados utilizando la notación bra-ket en la forma:
y los autovalores correspondientes como
Ahora tomamos un operador unario, Uω, que actúa como una subrutina que compara las diferentes entradas de acuerdo al criterio de búsqueda. El algoritmo no especifica como funciona la subrutina, pero debe ser una subrutina cuántica que trabaje bajo una superposición de estados. Además, debe actuar de manera especial sobre uno de los autoestados, |ω>, que corresponderá con la entrada que satisface el criterio de búsqueda. Más precisamente, requeriremos Uω con los siguientes efectos:
En concreto,
.
.
.
.
Nuestro objetivo es identificar el autoestado |ω>, o de manera equivalente, el autovalor ω, tal que Uω actúa especialmente sobre él.

Iteraciones del algoritmo

Los pasos del algoritmo de Grover son los siguientes:
  1. Inicializar el sistema al estado
  2. Realizar la siguiente iteración r (N) veces. Donde la función r (N) se describe más adelante.
    1. Aplicar el operador 
    2. Aplicar el operador .
  3. Realizar la medida Ω. La medida corresponderá al valor λω con una cierta probabilidad que se puede aproximar a 1, para un cierto N>>1. A partir de λω, se puede obtener ω.
Podemos escribir las operaciones realizadas:
.
.
.
Después de aplicar los dos operadores (  y  ), la amplitud del elemento buscado se ve incrementado. Y esta es una iteración de Grover.

Número de iteraciones

Ahora consideramos el plano definido por |s> y |ω>. Sea |ω×> que es perpendicular a |ω>. Entonces |ω> es uno de los vectores base, y tenemos
En términos geométricos, hay un ángulo (π/2 - θ) entre |ω> y |s>, where θ dado por:
El operador Uω es un reflejo del hiperplano ortogonal a |ω> para los vectors en el plano definido por |s> y |ω>, además, actúa como un reflejo de la línea |ω×>. El operador Us es un reflejo de la línea |s>.
Entonces, el vector de estado permanece en el plano de |s> y |ω> tras cada aplicación de Us y tras cada aplicación de Uω, y se puede comprobar que el operador UsUω de cada paso de iteración rota el vector de estado en un ángulo de 2θ hacia |ω>.
El algoritmo se detendrá cuando el vector de estado se acerca a |ω> tras esto, las siguientes iteraciones rotan el vector de estado fuera de |ω>, reduciendo la probabildad de obtener la respuesta correcta. El número de iteraciones necesarias es dado por r. Para alinear correctamente el vector de estado con |ω>, necesitamos:
Una consideración es que r debe ser entero, por lo que, en general, r será el entero más cercano a (π/θ - 2)/4. Entonces, el ángulo entre |ω> y el vector de estado final es O(θ), y la probabilidad de obtener una respuesta incorrecta es O(1 - cos2θ) = O (sin2θ).
Entonces, para N>>1, θ ≈ N-1/2, tenemos
Además, la probabilidad de obtener una respuesta incorrecta será O(1/N), que tiende a 0 para un valor de N suficientemente elevado.

Implementación

A continuación presentamos una implementación concreta del algoritmo de Grover. Supongamos que tenemos una secuencia de 2nelementos que vamos a referenciar por su índice x. Supongamos también que disponemos de una función f (x) que nos dice si el valor almacenado en la posición x es el que estamos buscando. En concreto sea f (x)=1 para el valor buscado y f (x)=0 para el resto.

Oráculo

Oráculo.
A partir de la función f (x) vamos a construir un oráculo, tal como se muestra en la figura de la derecha. El funcionamiento de este bloque es el mismo que el correspondiente del algoritmo de Deutsch-Jozsa. La operación de este bloque es:
Puesto que el último estado no se modifica, vamos a ignorarlo y escribiremos:

Inversión sobre la media

Inversión sobre la media.
El bloque que lo realiza se muestra en la figura de la derecha. Esta operación puede escribirse:
con .
Esta operación se interpreta como inversión sobre la media, pues si lo aplicamos sobre un estado genérico , obtenemos:
,
en donde 

Iteración de Grover

Algoritmo de Grover. En detalle se muestra una de las iteraciones.
Una iteración de Grover se compone de dos pasos:
  1. Aplicación del oráculo
  2. Inversión sobre la media
Por tanto, la iteración de Grover puede escribirse:
.
El algoritmo completo se muestra en la figura de la derecha.

Interpretación

Hagamos las cuentas para la primera iteración de Grover. Preparamos un estado haciendo pasar el qubit |0> (realmente compuesto de n ceros) a través de una puerta de Hadamard:
Este estado pasa a través del oráculo, obteniendo:
A continuación, aplicamos la inversión sobre la media, y obtenemos:
Interpretemos ahora este resultado. Supongamos que en la posición xi se encuentra el valor buscado, esto es, f (xi)=1 y para el resto, f (x)=0, obtenemos:
Como puede observarse, el término que nos interesa aumenta su amplitud en comparación con demás los términos. Repitiendo esta operación en varias iteraciones, este efecto se verá incrementado. Si al final del algoritmo hacemos un medición, muy probablemente obtendremos el valor buscado.
Un algoritmo de búsqueda es el que nos permite encontrar un elemento x0 en un conjunto posible de soluciones (estructura de datos) que cumpla una determinada proposición f(x). Dentro de este tipo de problemas están la búsqueda en una base de datos o el coloreado ordenado de una gráfica.
Si no sabemos nada sobre la estructura del espacio de soluciones estamos ante un problema desestructurado, como el que resolvió Lov K. Grover en 1996. Un ejemplo sería la búsqueda de un teléfono en una guía telefónica sin conocer el nombre. Clásicamente el mejor algoritmo aleatorio nos llevaría a un coste de O(N) (si se quiere N/2 consultas de media) para una base de datos de tamaño N. Con el algoritmo de Grover se mejora este resultado con una ganancia cuadrática de orden O(√N). El algoritmo de Grover es probabilístico, es decir, sólo da la respuesta correcta con cierta probabilidad (al contrario que el de Deutsch por ejemplo que era determinista).
Lógicamente nuestra proposición aquí está implementada por un oráculo que actúe de la siguiente forma:
Por tanto, asumimos que de entrada necesitaremos un registro fuente de n qubits tal que N=2n y uno adicional para almacenar la información de la función. (Nótese el hecho de que conocer de antemano x0 no es lo mismo que reconocerlo entre un conjunto de estados).
La estrategia será preparar un estado superposición de todas las entradas del catálogo:
después aplicar el oráculo que nos dé todos los valores de la veracidad de la proposición sobre las entradas:
para en último lugar desbalancear los pesos estadísticos de forma que halla suficiente probabilidad de encontrar el estado |x0>|1>. Para ello hay que utlizar las operaciones de cambio de signo e inversión sobre el promedio.
Se trata de aplicar un cambio de signo al elemento que cumpla la proposición, de forma que quede de algún modo marcado (figura).
En el algoritmo clásico esto ya supondría, lógicamente, el haberlo encontrado, pero recordemos que aquí el elemento sigue dentro de un estado global que todavía no podremos medir por no tener la suficiente certeza de que el resultado nos va a dar nuestro elemento. El operador a implementar será de la forma:
La forma de implementar este algoritmo es preparando un estado destino, tal como hicimos para el de Deutsch-Jozsa (inicializandolo a |1> y aplicando Hadamard), en |0> - |1>. De este modo el oráculo de la función nos dará un cambio de signo cuando ésta sea 1.
es decir, al no alterarse el segundo registro lo que se tiene es que:
De esta forma el oráculo marca la solución del problema, mediante el operador cambio de signo:
Para N=4 por ejemplo este operador oráculo se puede implementar mediante las siguientes puertas de tipo Toffoli, dependiendo de si el x0=0,1,2,3:

No hay comentarios:

Publicar un comentario