lunes, 31 de mayo de 2010

Complejidad de funciones.

bien pues esta vez me enfoco en el problema numero 2 del primer parcial bien pues este problema decia lo siguiente:

Análisis asintótico
Encuentre una función de complejidad asintótica f(n) así que la función g(n)
definida experimentalmente por doce puntos en la siguiente tabla sea O(f(n)) (este para el martes y Ω(f(n)) para el jueves) .
Justifique esto con una gráfica y discute la calidad de la cota obtenida.

bueno primero que nada partamos sobre que nos piden entonces, si lo que nos estan pidiendo es una grafica que sea O de otra esto quiere decir que tenemos que encontrar una grafica que sea superior para f(n) esto en el caso de los martes y una cota inferior (osea Ω(f(n)).

bueno primero que nada lo que podemos hacer es ubicar la grafica que nos dan comparandola con algunas otras que nos han dado en clase antes de basealgunas de ellas y las cuales voy a usar son estas

O(1)

Orden constante

O(log n)

Orden logarítmico

O(n)

Orden lineal

O(n log n)

Orden cuasi-lineal

O(n2)

Orden cuadrático

O(n3)

Orden cúbico

O(na)

Orden polinómico

O(2n)

Orden exponencial

O(n!) ó O(nn)

Orden factorial


bien el resto del tema esta en este documento anexo debido a limitaciones que tube con la pagina.
para ver el pdf del tema haz click aqui.
para descarga aqui





jueves, 20 de mayo de 2010

Algoritmo de Shor

Que tal compañeros esta vez vengo a mostrar una pequeña introducción a un tema que me pareció interesante y trata acerca del algoritmo de shor.


¿Que es exactamente o cual es su definición?


El algoritmo de Shor es un algoritmo cuántico para descomponer en factores un número N en tiempo O((log N)3) y espacio O(log N), así nombrado por Peter Shor.

Muchas criptografías de clave pública, tales como RSA, llegarían a ser obsoletas si el algoritmo de Shor es implementado alguna vez en una computadora cuántica práctica. Un mensaje cifrado con RSA puede ser descifrado descomponiendo en factores la llave pública N, que es el producto de dos números primos.

Los algoritmos clásicos conocidos no pueden hacer esto en tiempo O((log N)k) para ningún k, así que llegan a ser rápidamente imprácticos a medida que se aumenta N. Por el contrario, el algoritmo de Shor puede romper RSA en tiempo polinómico. También se ha ampliado para atacar muchas otras criptografías públicas.

Como todos los algoritmos de computación cuántica, el algoritmo de Shor es probabilístico: da la respuesta correcta con alta probabilidad, y la probabilidad de fallo puede ser disminuida repitiendo el algoritmo.

¿Que es un computador cuántico?

La computación cuántica es un paradigma de computación distinto al de la computación clásica. Se basa en el uso de qubits en lugar de bits, y da lugar a nuevas puertas lógicas que hacen posibles nuevos algoritmos. Una misma tarea puede tener diferente complejidad en computación clásica y en computación cuántica, lo que ha dado lugar a una gran expectación, ya que algunos problemas intratables pasan a ser tratables. Mientras un computador clásico equivale a una máquina de Turing, un computador cuántico equivale a una máquina de Turing indeterminista.

El problema que intenta solucionar el algoritmo de Shor es que, dado un número entero N, intentamos encontrar otro número entero p entre 1 y N que divida N.
El algoritmo de Shor consiste en dos partes:

1. Una reducción del problema de descomponer en factores al problema de encontrar el orden, que se puede hacer en una computadora clásica.
2. Un algoritmo cuántico para solucionar el problema de encontrar el orden.

punto 1 (la parte clásica):


1. Escoja un número pseudo-aleatorio a <>
2.Compute el mcd(a, N).podemos por ejemplo usar el aglrotimo de Euclides.
#algoritmo que nos permite encontrar eficientemente el máximo común divisor.

Si el mcd(a, N) ≠ 1, entonces es un factor no trivial de N, así que terminamos.
Si no, utilice el subprograma para encontrar el período para encontrar r, el período de la función siguiente:
f(x) = a^x mod N,
es decir el número entero más pequeño r para el cual
f(x + r) = f(x).
3. Si r es impar, vaya de nuevo al paso 1.
4. Si ar/2 ≡ -1 (mod N), vaya de nuevo al paso 1.
5. Los factores de N son el mcd(ar/2 ± 1, N). Terminamos.

punto 2 subprograma para encontrar el período (parte cuántica):


1. Comience con un par de registros qubits de entrada y salida con log2N qubits cada uno, e inicialícelos a
N^{-1/2} \sum_x \left|x\right\rangle \left|0\right\rangle
donde x va de 0 a N - 1.
2. Construya f(x) como función cuántica y aplíquela al estado antedicho, para obtener
N^{-1/2} \sum_x \left|x\right\rangle \left|f(x)\right\rangle
3. Aplique la transformada de Fourier cuántica al registro de entrada. La transformada de Fourier cuántica en N puntos se define como:
U_{QFT} \left|x\right\rangle = N^{-1/2} \sum_y e^{2\pi i x y/N} \left|y\right\rangle
Lo que nos deja en el estado siguiente:
N^{-1} \sum_x \sum_y e^{2\pi i x y/N} \left|y\right\rangle \left|f(x)\right\rangle
4. Realice una medición. Obtenemos un cierto resultado y en el registro de entrada y f(x0) en el registro de salida. Puesto que f es periódica, la probabilidad de medir cierto y viene dada por

N^{-1} \left| \sum_{x:\, f(x)=f(x_0)} e^{2\pi i x y/N} \right|^2 = N^{-1} \left| \sum_{b} e^{2\pi i (x_0 + r b) y/N} \right|^2
El análisis muestra ahora que cuanto más alta es esta probabilidad, tanto más el yr/N es cercano a un número entero.

5. Convierta a y/N en una fracción irreducible, y extraiga el denominador r ', que es un candidato a r.
6. Compruebe si f(x) = f(x + r '). Si es así terminamos.
7. Si no, obtenga más candidatos a r usando valores cercanos a y, o múltiplos de r '. Si cualquier candidato cumple las condiciones, terminamos.
8. Si no, vaya de nuevo al paso 1 del subprograma.

Esto me parece algo interesante para poder empezar a investigar, por ahora solo fue la parte introductoria por la cual también en estos momentos estoy investigando; como dato les dejo algunas paginas que encontré con información acerca del tema, la mayoría de ellas en ingles pero buscare información con la cual pueda estar en español también.


Pagina con algo de contenido acerca del tema
Pagina con explicación y códigos de simulacion del mismo
Explicacion del algoritmo con datos interesantes
wikipedia: lo único que encontré por ahora en español y que se encuentra en este blog (no necesario si se lee lo de arriba)

Actualizado

aqui un pdf. con informacion del mismo en español

para verlo online haz click en este Link.

para descarga este Link.

miércoles, 19 de mayo de 2010

Proyecto # 5

Algoritmo Detección de Ciclos (Cycle Detection Algorithm)

Liebre y Tortuga (Tortoise & Hare)

Bueno compañeros hoy me toca hablar acerca de la detección de ciclos y más detalladamente acerca del algoritmo liebre tortuga Creado por Robert W. Floyd antes de entrar a este algoritmo y su explicación primero debemos saber que es la detección de ciclos.

Concepto: la detección de ciclos sirve para identificar si estos existen dentro de un grafo.

Teniendo en cuenta esto se podría deducir que nuestro algoritmo nos ayudara de alguna manera a saber si existe o no, pero ese no es lo
único que nuestro algoritmo ara y es lo que veremos a continuación.

Nuestro algoritmo toma base de una fabula en la cual una liebre y una tortuga tiene una carrera en la cual la liebre evidentemente es mas rápida que la tortuga y esta avanza primero y regresa después para burlarse de esta por su lentitud; tomando en base a esto nuestro algoritmo cambia un poco la idea y decide que la liebre regrese pero para advertir de posibles ciclos a la tortuga.

esto quiere decir que en nuestro algoritmo el papel de la liebre será la que pruebe los distintos tipos de caminos entre las opciones de una arista de manera de conseguir siempre el camino más corto esto se logra haciendo que la liebre este adelante de la tortuga.


Tal como
podemos ver en esta imagen la tortuga esta en un punto x1= 0 mientras la liebre lee el
paso siguiente e
n un punto x2 = 6 cada uno con
su respectivo valor.

Al no tener el mismo la tortuga avanza una posición y la liebre avanza dos

Podemos ver entonces que ahora la tortuga se encuentra en un estado ((x1+1) = x2) = 6 y la liebre en un estado
((x2+2)=x4) = 1 al no ser iguales los valores avanzan y repetimos la instrucción

En esta parte la tortuga se encuentra ahora en la posición((x2+1)=x3)=3 y la liebre en una posición
((x4+2)=x6)=3 al encontrarse con un mismo valor en diferentes posiciones se llega a un ciclo y es aquí donde la tortuga toma una ruta distinta en su siguiente paso no se llegase a tener












Esta sería la representación en un grafo claro este solo sería el ejemplo de que pasaría si encuentra un ciclo.















Aquí prácticamente seria repetir exactamente lo escrito arriba así que solo me limitare a decir que esto equivale al paso uno en donde se evalúa cada valor en el grafo.













En esta parte ya la tortuga ah avanzado una posición y se encuentra en 6 mientras la liebre esta en 1.



















Aquí por ultimo vemos que ambos quedaron en la misma posición en este momento el algoritmo reconoce que es un ciclo al tener la liebre y la tortuga el mismo valor por lo cual el camino resulta ineficiente para llegar a la meta indicada.

Con respecto al análisis asintótico de este algoritmo me tope con ciertas dudas dado que su complejidad en O (λ+μ) donde
λ: representa una parte de otra función ya sea f(n).
μ: está definida para todos los números naturales n y tiene valores en {-1, 0, 1} dependiendo en la factorización de n en sus factores primos. (véase este enlace para aclarar dudas)

y tomando en cuenta eso (y suponiendo que los términos estén correctos) se puede decir que la complejidad asintótica del algoritmo depende en cierta forma de la función f(n) del programa y esta a su vez seria la cual afecte a μ ya que dependerá de si f(n) es Ωf(n) pues en base a ello tomara un valor si Ωf(n) = ω(n) ó Ωf(n)>ω(n).

la complejidad computacional debería ser polinomial pues es precisamente lo que hace el algoritmo al tener dos punteros uno con el doble de velocidad que el segundo llámense "a" y "b"
"b" como primera opción siempre intentara buscar el camino más corto al punto deseado pero a su vez topara con ciclos si estos existen mientras "a" ira más lento pero llegara por la ruta más corta al evitar los caminos que se repitan recorridos por "b", y si estos no llegaran a llevar a la meta y solo se produjera un ciclo del cual no se puede salir pues el algoritmo llegaría a su fin al no llegar al punto establecido.

pseudocódigo del algoritmo
este es un pequeño pseudocódigo que encontré que muestra prácticamente lo que se dice arriba

def floyd(f, x0):
---------------------------------------------------------------------------------

# La fase principal del algoritmo,buscara una repeticion x_mu = x_2mu
# La Liebre se Mueve dos veces mas rapido que la tortuga
tortuga, liebre = f(x0), f(f(x0)) # f(x0) es el elemento ó nodo siguiente de x0.
while tortuga != liebre:
tortuga = f(tortuga)
liebre = f(f(liebre))

# encontrar la posicion de la primera repeticion de la longitud "mu"
# La tortuga y la liebre se mueven ala misma velocidad
mu = 0
tortuga, liebre = x0, tortuga
while tortuga != liebre:
tortuga = f(tortuga)
liebre = f(liebre)
mu += 1

# encontrar la longitud del cyclo mas corto empezando de x_mu
# la liebre se mueve mientras la tortuga se queda sin moverse
lam = 1
liebre = f(tortuga)
while tortuga != liebre:
tortuga = f(liebre)
lam += 1

return lam, mu

------------------------------------------------------------------------

nota: cabe recordar que los dialogos despues del simbolo "#" representan un comentario en el pseudocodigo.

hay que tener en cuenta que este código solo tiene acceso a la secuencia mediante el almacenamiento y la copia de punteros, evaluaciones de la función, y las pruebas de la igualdad, por lo que califica como un algoritmo de puntero.

Las estructuras de datos utilizadas en este algoritmo son:
listas, arreglos, punteros, funciones.

aquí incluyo un ejemplo de dicho algoritmo en un programa si desean pueden copiar el código o descargarlo directamente desde la pagina del creador en los links de la parte de abajo.
-------------------------------------------------------------------------
#include


typedef struct node_s {
void *data;
struct node_s *next;
} NODE;


int list_has_cycle(NODE *list)
{
NODE *fast=list;
while(1) {
if(!(fast=fast->next)) return 0;
if(fast==list) return 1;
if(!(fast=fast->next)) return 0;
if(fast==list) return 1;
list=list->next;
}
return 0;
}


int main()
{
NODE n1, n2, n3, n4, n5;

n1.next=&n2;
n2.next=&n3;
n3.next=&n4;
n4.next=&n5;
n5.next=NULL;

printf("Test without cycle: ");
if(list_has_cycle(&n1)) printf("cycle\n");
else printf("no cycle\n");


n5.next=&n3;

printf("Test with cycle: ");
if(list_has_cycle(&n1)) printf("cycle\n");
else printf("no cycle\n");

return 0;
-------------------------------------------------------------------
dentro del código podemos ver que si los nodos n siguen su paso hasta un estado n5 = NULL se logra llegar al estado deseado por lo tanto no hay un ciclo en el transcurso pero si cambiásemos dicha ruta por una ya escrita tal como se ve en la línea donde n5=&n3 regresamos de nueva cuenta hacia n3 donde este toma el valor de n4 y así sucesivamente es por eso que utilizamos nuestra función list_has_cycle para que en la decisión imprima si existe o no un ciclo.


Detección de ciclos (explicación en ingles)

Biografía del Autor de Dicho algoritmo
Pagina web de apoyo para mi reporte
Otra web de apoyo.
*me falto anexar algunos archivos pdf de los cuales base la investigacion que subire en estos dias para que tmb pase a revisarlos.


Seguidores