Está en la página 1de 5

Backtracking:Dentro de las técnicas de diseño de algoritmos, el método de Vuelta Atrás (del inglés Backtracking) es uno de los de más

amplia utilización, en el sentido de que puede aplicarse en la resolución de un gran número de problemas, muy especialmente en aquellos de optimización. En ocasiones se ven enfrentados aproblemas de optimización que solo pueden ser resueltos a través de un estudio exhaustivo de un conjunto conocido a priori de posibles soluciones, en las que se trata de encontrar una o todas las soluciones y por tanto también la óptima. Para llevar a cabo este estudio exhaustivo, el diseño Vuelta Atrás proporciona una manerasistemática de generar todas las posibles soluciones siempre que dichas soluciones sean susceptibles de resolverse en etapas. Contenido
[ocultar]

  

1 Técnica de Backtracking 2 Algoritmo Genético 3 Eficiencia y complejidad del método

 

4 Recursividad 5 Fuentes

Técnica de Backtracking
En su forma básica la Vuelta Atrás se asemeja a un recorrido en profundidad dentro de un árbol cuya existencia sólo es implícita, y que se denomina árbol de expansión. Este árbol es conceptual, en donde cada nodo de nivel k representa una parte de la solución y está formado por k etapas que se suponen ya realizadas. Sus hijos son las prolongaciones posibles al añadir una nueva etapa. Para examinar el conjunto de posibles soluciones es suficiente recorrer este árbol construyendo soluciones parciales a medida que se avanza en el recorrido. En este recorrido pueden suceder dos cosas. La primera es que tenga éxito si, procediendo de esta manera, se llega a una solución (una hoja del árbol). Si lo único que buscábamos era una solución al problema, el algoritmo finaliza aquí; ahora bien, si lo que se busca eran todas las soluciones o la mejor de entre todas ellas, el algoritmo seguirá explorando el árbol en búsqueda de soluciones alternativas. Por otra parte, el recorrido no tiene éxito si en alguna etapa la solución parcial construida hasta el momento no se puede completar; s encuentran en lo que llamamos nodos fracaso. En tal caso, el algoritmo vuelve atrás (y de ahí su nombre) en su recorrido eliminando los elementos que se hubieran añadido en cada etapa a partir de ese nodo. Si en este retroceso, si existe uno o más caminos aún no explorados que puedan conducir a solución, el recorrido del árbol continúa por ellos.

Algoritmo Genético
El algoritmo genérico del backtracking es el siguiente: Inicio IniciarOpciones; Repetir SeleccionarNuevaOpcion; Si Aceptable entonces

A este paso se le denomina expansión. aunque siempre asegurar de que el árbol “podado” siga conteniendo todas las soluciones. Queda por tanto el siguiente esquema general para este caso: Algoritmo BacktrackingTodaslasSoluciones(etapa) Inicio IniciarOpciones. y para cada uno de estos descendientes. Si SolucionIncompleta entonces BactrackingTodaslasSoluciones(etapa_siguiente). Si SolucionIncompleta entonces Backtracking(etapa_siguiente). En este esquema se puede observar que están presentes tres elementos principales. y para ello han de pensar en la propia recursión y su mecanismo de funcionamiento. Si Aceptable entonces AnotarOpcion. End Else /*Solución Completa*/ Éxito = true. Finalmente. que es la que permite ir recorriendo el árbol en profundidad. En primer lugar hay una generación de descendientes. A continuación. Cuando se desea encontrar todas las soluciones habrá que alterar ligeramente el esquema dado. Else ComuncicarSolucion. de forma que una vez conseguida una solución se continúe buscando hasta agotar todas las posibilidades. aplicaran la prueba de solución (tercer elemento) que comprueba si el nodo que es posible solución efectivamente lo es. End BacktrackingTodaslasSoluciones. debe de aplicar lo que se denomina prueba de fracaso (segundo elemento). Por otra parte debe tener cuidado a la hora de . Until(UltimaOpcion).Inicio AnotarOpcion. Eficiencia y complejidad del método Gran parte de la eficiencia (siempre relativa) de un algoritmo de Vuelta Atrás proviene de considerar el menor conjunto de nodos que puedan llegar a ser soluciones. CancelarAnotacion. Repetir SeleccionarNuevaOpcion. Tal vez lo más difícil de ver en este esquema es donde se realiza la vuelta atrás. en donde para cada nodo generamos sus descendientes con posibilidad de solución. Si NOT éxito entonces CancelarAnotacion. End End Until(Exito) OR (UltimaOpcion) End Backtracking. ramificación o bifurcación. caso de que sea aceptable este nodo. End. End.

si hay algún problema. ¿El caso base? Cuando el tablero se haya reducido a uno de . El problema consiste en situar ocho reinas en el tablero de tal forma que no se den jaque entre ellas. se deshace el último movimiento y se prueba a localizar una casilla alternativa. la octava. por último. pero sin embargo en muchos casos no son suficientes para conseguir algoritmos “tratables”. podrías decir que las restricciones sencillas son siempre apropiadas. trata de reducir este número tanto como sea posible. se intentará emplazar la séptima y. columna o diagonal en la que se encuentra dicha reina. elimina como posibles casillas donde localizar reinas la fila. para lograr esto sólo debe de ir variando el orden en el que se generan los descendientes de un nodo. si no se utilizan restricciones. en situar una reina en cada fila y en cada columna. Si no se consigue. Suponiendo que se han situado las seis primeras reinas. es de orden de zⁿ donde z son las posibles opciones que existen en cada etapa. En ella se van dando pasos hacia delante mientras sea posible y se deshacen cuando se ha llegado a una situación que no conduce a la resolución del problema original. Al hacer esto. De esta forma estos algoritmos van a ser de un orden de complejidad al menos del número de nodos del árbol que se generen y este número. Y como la búsqueda que realiza la Vuelta Atrás es siempre en profundidad. tanto implícitas como explícitas. se sitúa en la segunda columna la segunda reina y se "tachan" las nuevas casillas prohibidas. y como norma de actuación general. Una reina puede dar jaque a aquellas reinas que se sitúen en la misma fila. el cual tiene un total de 64 casillas (8 filas x 8 columnas). Para aquellos problemas en donde se busca una solución y no todas. Teniendo en cuenta estas restricciones. se vuelve hacia atrás y así sucesivamente. de manera que aquellas restricciones que vayan a detectar pocos nodos fracaso no serán normalmente interesantes. Si no se pudiera. En el caso de que no sea posible. la profundidad del árbol o la longitud de la n-tupla solución). Si se ha conseguido sin que le den jaque. es donde entra en juego la posibilidad de considerar distintas formas de ir generando los nodos del árbol. Sin embargo esta evaluación requiere a su vez tiempo extra. se deshace el movimiento que ha ubicado la sexta reina y busca otra posición válida para dicha reina. En este momento realizaría una llamada recursiva. En ese momento. La solución a este rompecabezas pasa. mientras que las más sofisticadas que requieren más tiempo en su cálculo deberían reservarse para situaciones en las que el árbol que se genera sea muy grande. la columna y las dos diagonales. Usualmente los algoritmos Vuelta Atrás(backtracking) son de complejidad exponencial por la forma en la que se busca la solución mediante el recorrido en profundidad del árbol. No obstante. ¿Cómo actuará para situar las ocho reinas? Comenzará por la primera columna y situará la primera reina. se sigue hacia atrás intentando colocar la reina quinta. por tanto. Ejemplo 1: Problema de las 8 reinas.decidir el tipo de condiciones (restricciones) que comprueban en cada nodo a fin de detectar nodos fracaso. Seguidamente se procede a poner la tercera reina y así sucesivamente. y n el número de etapas que es necesario recorrer hasta construir la solución (esto es. hay que considerar el problema de situar otra reina en la columna siguiente: resolver el mismo problema con una columna menos. Si se puede colocar. al delimitar el tamaño del árbol a explorar. Evidentemente el análisis de estas restricciones permite ahorrar tiempo. En general. El uso de restricciones. es decir. se vuelve deshacer el movimiento de la sexta reina y se intenta buscar otra localización. Recursividad ¿Cómo se puede aplicar la recursividad para solventar este problema? De forma muy sencilla: dado que se ha situado una reina en una posición correcta en una columna. que sus tiempos de ejecución sean de orden de complejidad razonable. de manera que trate de ser lo más apropiado a nuestra estrategia. entonces se procederá a dejar en el tablero la sexta de nuevo. Puede llegar un momento en el que no se pueda situar la séptima sin que ninguna otra le dé jaque. Parte de un tablero de ajedrez.

momento en el cual habrá alcanzado el caso base.1] y [n. Por tanto. Dada una matriz con un laberinto. Var . Al producirse la vuelta atrás se cuidará de liberar las casillas ocupadas por el nodo del que volvemos (marcándolas de nuevo con 0). Si se puede situar una reina en la columna correspondiente. el algoritmo es sencillo: Algoritmo Laberinto(k:Cardinal. El algoritmo de las 8 reinas seria el siguiente: Algoritmo Reinas(k:CARDINAL). se hace una llamada recursiva. X[k]:=0. Las casillas [1.col:Integer. y cada nodo representará el camino recorrido hasta el momento. (* iniciar opciones *) Repetir INC(X[k]). y se considerarán problemas de tamaño menor quitando una columna en cada llamada recursiva hasta que se llegue a un tablero de tamaño cero.tamaño cero.Var fil. Solución En este problema debe ir avanzando por el laberinto en cada etapa. se vuelve hacia atrás y se prueba otras posiciones. realizando la prueba de fracaso. Por la forma en la que trabaja el esquema general de Vuelta Atrás puede utilizar una variable global (una matriz) para representar el laberinto e ir apuntando los movimientos que realiza. Fin Donde la función Valido es la que comprueba las restricciones implícitas. para ir de la entrada a la salida. Con esto en mente. (* seleccion de nueva opcion *) Si Valido(k) entonces (* prueba de fracaso *) Si k<>n entonces Reinas(k+1) (* llamada recursiva *) sino ComunicarSolucion(X) end end Hasta que (X[k]=n). el problema consiste en diseñar un algoritmo que encuentre un camino.n] corresponden a la entrada y salida del laberinto y siempre serán transitables. (* encuentra todas las maneras de disponer las n reinas *) Inicio Si k>n entonces RETURN end. indicando en cada casilla el orden en el que ésta ha sido visitada. Ejemplo2: Laberinto Una matriz bidimensional nxn puede representar un laberinto cuadrado. se partirá de un problema de tamaño 8. Cada posición contiene un entero no negativo que indica si la casilla es transitable (0) o no lo es (∞). Var exito:Boolean). si existe. en cuyo caso no se hará nada. si no.

Las variables mov_fil y mov_colcontienen los posibles movimientos. fil:=fil + mov_fil[orden].4]OF INTEGER. (* este *) mov_fil[3]:=0. Si (fil=n) AND (col=n) entonces exito:=TRUE sino Laberinto(k+1.exito). Inicio mov_fil[1]:=1.mov_col[orden] End Until (exito) OR (orden=4) End (*Laberinto*). y son inicializadas por el procedimiento MovimientosPosibles que mostramos a continuación: VAR mov_fil. mov_col[4]:=0..col]:=0 End End End fil:=fil .col]:=k.orden:CARDINAL.mov_fil[orden]. exito:=FALSE. .mov_col:ARRAY [1. mov_col[3]:=-1. (*indica hacia donde debe moverse *) Inicio orden:=0.col.fil. Repetir INC(orden).col]=0) entonces lab[fil. (* sur *) mov_fil[2]:=0. mov_col[2]:=1. col:=col + mov_col[orden]. Si NOT exito entonces lab[fil. col:=col . Algoritmo MovimientosPosibles. (* oeste *) mov_fil[4]:=-1. (* norte *) End (*MovimientosPosibles*). Si (1<=fil) AND (fil<=n) AND (1<=col) AND (col<=n) AND (lab[fil. mov_col[1]:=0.