sábado, 29 de mayo de 2010

Backtracking

En esta ocasión hablaremos de los algoritmos backtracking (algoritmos de vuelta atrás), este método para la resolución de problemas funciona a prueba y error, lo cual lo hace un algoritmo de mucho costo en cuanto a tiempo para encontrar la solución, ya que el probara todas las opciones para llegar a solucionar el problema, pero esto nos asegurara la mejor solución al problema planteado.

La más antigua referencia a Backtracking, es la historia del hilo de Ariadna en la mitología griega. Su padre, el rey Minos de Creta detentaba su tiránico poder sobre su isla y por conquista sobre Atenas. El tributo que pedía de los atenienses consistía en grupos de jóvenes que entraban a su laberinto donde habitaba el Mino tauro (mitad hombre, mitad toro) para encontrar la muerte a manos de éste. El héroe ateniense Teseo se ofreció voluntariamente a acompañar a un grupo dejóvenes que se iban a sacrificar para salvar a Atenas de ésta cruel tradición.

Ariadna se enamoró de Teseo y le regaló un ovillo de hilo dorado para que no se perdiera en el laberinto. La idea era que Teseo desenrollara el ovillo a medida que avanzara por el laberinto, si llegaba a un callejón sin salida tenía que volver atrás y enrollar el hilo hasta llegar al punto donde había escogido dicho camino para intentar una ruta alternativa. El Backtracking funcionó, Teseo asesinó al Mino tauro y escapó del laberinto, y de la isla de Creta con los jóvenes y con Ariadna.

Lo primero que se hace para identificar un problema digno de Backtracking es pensar cómo lo resolverá el usuario como humano; si su mejor solución es empezar con algunas condiciones iniciales e ir probando caminos, hasta llegar a un punto en donde no hay solución y regresar entonces un poco para explorar por otro lado, está pensando en función de Backtracking. Lo más importante para hacer un Backtracking es hacer un “retroceso mínimo”, o sea, no destruir todo si no pudo encontrar una solución, sino sólo borrar lo necesario para poder seguir explorando sin perder todo el camino que has recorrido.

El caso más similar a lo que se debe hacer para implementar un Backtracking es pensar en la manera como se sale de un laberinto, primero se amarra un hilo en el principio del laberinto y se va decidiendo sobre cada bifurcación hacia dónde va a seguir; al momento de encontrar un callejón sin salida sabe que debe regresar y buscar por el lado contrario; si los dos lados no lo llevan a la salida entonces podrá marcar esa bifurcación con alguna señal, regresar más y buscar otro camino. Es lo que se haría en pocas palabras, porque nunca se debería regresar hasta el principio al encontrar un callejón sin salida, se debería retroceder lo menos posible siguiendo al hilo que indica lo que se ha recorrido y no se debería volver a entrar a caminos ya marcados.

La técnica de Backtracking es usada en muchos ámbitos de la programación, por ejemplo, para el cálculo de expresiones regulares o para tareas de reconocimiento de texto, desarrollo de video juegos y de sintaxis de lenguajes regulares. También es usado incluso en la implementación de algunos lenguajes de programación, tales como Planner o Prolog y da soporte a muchos algoritmos en inteligencia artificial.

Dado que en cada llamada recursiva se invoca 2 veces a la misma función y como hay n vocaciones por cada llamada recursiva, su complejidad es: 0(2n)

Note que al tener una complejidad exponencial, el Backtracking no es una técnica muy eficiente, pero su ventaja es que siempre encontrará la solución si es que existe y si tuviéramos todo el tiempo del mundo.

Conclusión
Como se ha mencionado el backtracking es una herramienta muy útil, ya que nos ayuda a resolver problemas grandes en los que no se sabe cual camino tomar, este algoritmo ira buscando la mejor solución a prueba y error, si bien es una algoritmo que nos dará la respuesta requerida no es un algoritmo eficiente, es por esta razón que es un algoritmo heurístico.

Es interesante como cosas tan sencillas se pueden aplicar a la resolucion de problemas diario, como resolver el cubo de Rubik o cubo magico.


sábado, 22 de mayo de 2010

Estructura de datos XML

El XML lenguaje de marcación extensible por sus siglas en ingles, no es cómo podríamos pensar por su nombre un lenguaje de marcado. XML es un meta-lenguaje que nos permite definir lenguajes de marcado algo similar a el HTML. Pero por esta razón no es XML una mejora a HTML o una evolución de HTML.

Aunque a primera vista, un documento XML puede parecer similar a HTML, hay una diferencia principal. Un documento XML contiene datos que se autodefinen, exclusivamente.
Un documento HTML contiene datos mal definidos, mezclados con elementos de formato. En XML se separa el contenido de la presentación de forma total.

Los documentos XML deben seguir una estructura estrictamente jerárquica con lo que respecta a las etiquetas que delimitan sus elementos. Una etiqueta debe estar correctamente "incluida" en otra. Además, los elementos con contenido, deben estar correctamente "cerrados". La siguiente imagen muestra la estructura de un documento en XML

Todo documento en XML posee una estructura lógica y una física. Físicamente el documento está compuesto de unidades llamadas entidades. Una entidad puede hacer referencia a otras entidades para que estas sean incluidas en un documento, un documento en XML empieza en la raíz. Como se mira en el siguiente ejemplo:

Como se ha mencionado anteriormente un documento XML posee una estructura jerárquica, del ejemplo anterior este sería el diagrama Jerárquico:
Conclusión
Si bien el XML es una meta-lenguaje parecido al HTML son lo mismo, ya que el XML permite definir estructuras más simples y legibles, es por esta razón que se ha convertido en uno de los favorito entre los programadores que lo usan para sus conexiones a bases de datos, sitios web entre otros.

http://www.tesis.ufm.edu.gt/pdf/2995.pdf

sábado, 15 de mayo de 2010

Matrices de Adyacencia para representación de Grafos Dirigidos

Iniciaremos diciendo que un grafo dirigido consiste en un conjunto de vértices V y un conjunto de arcos, los vértices también pueden llamarse nodos o puntos, los arcos pueden llamarse arcos dirigidos o líneas dirigidas.

Los arcos son pares ordenados de vértices (A, B), donde A es la cola y B la cabeza del arco, y se expresa como A -> B.

La punta de la flecha esta en el vértice llamado cabeza y la cola en el vértices llamado cola se dice que el arco A -> B va de A a B y B es adyacente a A.

Para la representación de un grafo dirigido se pueden usar varias estructuras de datos, la selección dependerá de las operaciones que se les aplicara a los vértices. Una representación común de un grafo dirigido es la matriz de adyacencia.
Sea G= (V, A) un grafo, donde V= {1, 2, 3. . ., n}. La matriz de adyacencia para G es una matriz booleana de dimensión nxn, donde cada elemento [i, j] vale 1 si y solo si, existe un arco (i, j).
La principal desventaja de usar una matriz de adyacencia para representar un grafo dirigido es que requiere un espacio Ω (n2) aun si el grafo dirigido tiene menos de n2, Solo leer y examinar un matriz de adyacencia puede llevar un tiempo O (n2).

Para evitar esta desventaja se puede utilizar otro método común para un grafo dirigido, llanada representación con lista de adyacencia. El grafo está representado por un arreglo de listas de adyacencia. Sea G= (V, A) un grafo, donde V= {1, 2, 3. . ., n}. La lista de adyacencia para un vértice i es una lista, en algún orden, de todos los vértices adyacentes a i. Se puede representar G por medio de un arreglo H, donde H[i] es un apuntador a la lista de adyacencia del vértice i.

Conclusión
Usar matrices de adyacencia será fácil pero tiene una complejidad de tiempo más cara que usar las listas de adyacencia.

http://es.wikibooks.org/wiki/Estructuras_de_datos_dinamicas/Grafos
http://www.ucfunciones.webs.com/TeoriaDeGrafos/Representacion_de_grafos.pdf

sábado, 1 de mayo de 2010

Algoritmos recolectores de basura

Cuando ejecutamos programas estos instancian objetos y asignan espacios en memoria para su uso durante su ejecución. Al terminar su ejecución estos dejan los espacios o huecos y en algunos casos información basura en memoria, cuando ya no queda más espacio disponible, o cuando la rutina de recolección de basura se ejecuta, la memoria se compacta, colocando todos los objetos que se están usando al inicio y así elimina los espacios que ya no son usados en memoria, quedando así espacio en memoria para creación de nuevos objetos.

Como se muestra en la siguiente imagen al crear objetos se van llenado diferentes espacios en memoria (representado con colores cada asignación de memoria), al salir de estos programas se liberan espacios o se deja la información, es aquí donde la memoria se compacta y así reorganiza los objetos.

Aunque en algunos lenguajes de programacion ya cuentan con recolectores de basura implitos, entre ellos se encuentran: ALGOL 68, BASIC, C#, Java, JavaScript, Modula-3, Perl,PHP, Prolog, Python, Ruby, Smalltalk.

Estos algoritmos de recolección los que vienen implícitamente en los lenguajes o los creados, son importantes ya que sin ellos la memoria sufriría de sobrecarga en cuanto a información o basura que se almacena en ella y no es liberada.

Teniendo en consideración que si el programador desea crear el algoritmo de recolección de basura tendrá que ser cuidados con esta tarea ya que podría cometer errores y liberar espacio que están siendo usados por otros programas y en perores casos por el SO.