SlideShare una empresa de Scribd logo
Vuelta atrás o  Backtracking 1. Método general. 2. Análisis de tiempos de ejecución. 3. Ejemplos de aplicación. 3.1. Problema de las 8 reinas. 3.2. Problema de la mochila 0/1.
Método general El  backtracking   (método de  retroceso  ó  vuelta atrás ) es una técnica general de resolución de problemas, aplicable tanto a problemas de  optimización ,  juegos  y otros tipos. El  backtracking  realiza una  búsqueda exhaustiva  y sistemática en el espacio de soluciones. Por ello, suele resultar ineficiente. La  solución  de un problema de backtracking se puede expresar como una  tupla (x 1 , x 2 , ..., x n ) , satisfaciendo unas restricciones P(x 1 , x 2 , ..., x n ) y tal vez optimizando una cierta función objetivo. En cada momento, el algoritmo se encontrará en un cierto  nivel  k , con una  solución parcial (x 1 , ..., x k ) . Si se puede añadir un nuevo elemento a la solución  x k+1 , se genera y se avanza al nivel  k+1 .
Método general Si no, se prueban otros valores de  x k . Si no existe ningún valor posible por probar, entonces se  retrocede  al nivel anterior  k-1 . Se sigue hasta que la solución parcial sea una solución completa del problema, o hasta que no queden más posibilidades. El resultado es equivalente a hacer  un  recorrido en profundidad  en el árbol de soluciones. Sin embargo, este árbol es  implícito , no se almacena en ningún lugar. Ejemplo .  Dado un conjunto de números enteros {13, 11, 7}, encontrar si existe algún subconjunto cuya suma sea exactamente 20.
Método general Posibilidad 1)  Árbol binario: En cada nivel  i  decidir si el elemento  i  está o no en la solución. Representación de la solución: (x 1 , x 2 , x 3 ), donde x i = (0, 1). Cada nodo representa un paso del algoritmo, una solución parcial en cada momento dado. El árbol indica un orden de ejecución (recorrido en profundidad) pero no se almacena en ningún lugar. Una solución es un nodo hoja con valor de suma 20. Posible mejora : En cada nodo llevamos el valor de la suma hasta ese punto. Si el valor es mayor que 20: retroceder al nivel anterior. Árbol de soluciones 1 k=1  (13) k=2  (11) k=3  (7) 1 0 1 5 2 3 6 4 8 7 0 1 0 1 0 1 12 9 10 13 11 15 14 0 1 0 1 0 1 0 7 11 13 18 20 24 31 Sumas totales
Método general Posibilidad 2)  Árbol combinatorio: En cada nivel  i  decidir qué elemento se añade (1, 2 o 3). Representación de la solución (s 1 , ..., s m ), donde m  n y s i     {1, 2, 3}. Árbol de soluciones 2 Cada nodo es una posible solución. Será válida si la suma es 20. El recorrido es también en profundidad. Necesitamos funciones para generar los nodos, para descartar nodos y para saber si un nodo es solución. ¿Cómo será la eficiencia del algoritmo? Depende del número de nodos. k=1 k=2 k=3 1 3 2 3 5 4 3 3 2 7 6 3 31 2 1 8 0 13 11 20 18 7 24
Método general Esquema general  (sin recursividad) . Suponiendo que existe al menos una solución y que queremos obtener una cualquiera. Backtracking (var s: array [1.. Max_nivel] of tipo) nivel = 1 fin = false repetir   s[nivel] =  Generar (nivel, s)   si  Solución (nivel, s) fin = true   en otro caso si  Criterio (nivel, s)   nivel = nivel + 1   en otro caso mientras no  MasHermanos (nivel, s) Retroceder (nivel, s) hasta fin=true
Método general Variables : s : Almacena la solución (un array, desde 1 hasta el nº máximo de niveles). nivel : Indica el nivel actual en el que se encuentra el algoritmo. fin : Valdrá  true  cuando hayamos encontrado alguna solución. Funciones : Generar (nivel, s) : Genera el siguiente hermano (o el primero) para el nivel actual. Devuelve el siguiente valor a añadir a la solución parcial actual (depende de la solución parcial y del nivel). Solución (nivel, s) : Comprueba si la solución (s[1], ..., s[nivel]) es una solución válida para el problema. Criterio (nivel, s) : Comprueba si a partir de (s[1], ..., s[nivel]) se puede alcanzar una solución válida, o si se puede mejorar la actual. En otro caso se rechazarán todos los descendientes.
Método general Funciones : MasHermanos (nivel, s) : Devuelve verdad si hay más hermanos del nodo actual que todavía no han sido generados. Retroceder (nivel, s) : Retrocede un nivel en el árbol de soluciones. Disminuye en 1 el valor de  nivel , y posiblemente tendrá que actualizar la solución actual, quitando los elementos retrocedidos. ¿Cómo serían estas funciones en los ejemplos anteriores? Otros   posibles casos  de problemas : 1)  No está garantizado que exista una solución, puede existir alguna o no. 2)  Queremos obtener todas las soluciones, no sólo una. 3)  El problema es de optimización. De todas las soluciones posibles queremos aquella que maximice (o minimice) una función objetivo.
Análisis de tiempos de ejecución El tiempo de ejecución depende del número de nodos generados y del tiempo requerido para cada nodo, que viene dado por el coste de las funciones. Suponiendo que una solución sea de la forma: (x 1 , x 2 , ..., x n ), en el peor caso se generarán todas las posibles combinaciones para cada  x i . Si el número de posibles valores para cada  x i  es  m i , entonces se generan: m 1 nodos en el nivel 1 m 1 ·m 2 nodos en el nivel 2   ... .... m 1 ·m 2 · ... ·m n nodos en el nivel n Ejemplo :  para el problema de la suma de subconjuntos m i  = 2. El número de nodos generados es: t(n) = 2 + 2 2  + 2 3  + ... + 2 n  = 2 n+1  - 2 Ejemplo : calcular todas las permutaciones de (1, 2, ..., n). En el nivel 1 tenemos n posibilidades, en el nivel 2 n-1, ..., en el nivel n una posibilidad. t(n) = n + n·(n-1) + n·(n-1)·(n-2) + ... + n!    O(n!) En general tendremos tiempos con órdenes de complejidad factoriales o exponenciales.
Problema de las n reinas Problema :  Dado un tablero de ajedrez de tamaño  nxn , encontrar una forma (o todas) de colocar  n  reinas, sin que ninguna de ellas pueda comerse a otra. Solución 1 :  Probar todas las posiciones posibles y para cada una comprobar si es válida. Para tamaño 8: 4.426 1 165.368 posibilidades. Solución 2 :  Colocar cada reina en cada fila. Una solución será un array  de 1..8. Para cada reina se probarán cada una de las 8 columnas. Habrá que probar: 8 8  = 16 1 777.216 posibilidades. Solución 3 :  No colocar dos reinas en una misma columna. La solución será una permutación de los números (1, 2, ..., 8): 8! = 40.320 posibilidad. Error :  No se comprueba si la situación es correcta hasta el final.
Problema de las n reinas Solución con backtracking. Características :  Puede existir solución o no. No es un problema de optimización. Suponemos que buscamos todas las soluciones.  Representación . Array solución:  s : array [1..8] of 0..8. s[i] = j . La reina de la fila  i  está en la columna  j . Recorrido  con backtracking:  En cada nivel  i , probar las formas de colocar la reina de la fila  i , desde la columna 1 hasta la 8. La  posición  será  válida  (podemos avanzar de nivel) si la reina  i  no está en la misma columna o diagonal que alguna de las reinas anteriores.
Problema de las n reinas Funciones: Generar (nivel, s) . Probar primero la posición 1, luego la 2, ..., hasta la 8. MasHermanos (nivel, s) . Cierto si s[nivel] es menor que 8. Criterio (nivel, s) . Comprobar si la reina de la posición s[nivel] no se come a las anteriores (1, 2, ..., nivel-1). Solución (nivel, s) .  Cierto si el nodo es una hoja (nivel = n) y se cumple Criterio. Retroceder (nivel, s) . Quitar la reina de la posición nivel. s[nivel]:= 0 (valor de inicialización).
Problema de las n reinas NReinasBacktracking (var s: array [1.. n] of integer) nivel = 1 s[1] = 0 repetir   s[nivel] = s[nivel] + 1   mientras (s[nivel]    n) y no Criterio (nivel, s) s[nivel] = s[nivel] + 1   si (nivel=n) y (s[nivel]    n)  MostrarSolucion (s)   en otro caso si (s[nivel]    n) nivel = nivel + 1 s[nivel] = 0   en otro caso nivel = nivel -1 hasta nivel = 0 Criterio (nivel: 0..n; s: array [1.. n] of integer) : boolean para i = 1,2,...,nivel-1    si (s[nivel]=s[i]) o |s[i] - s[nivel]| = |i - nivel| Devolver false Devolver true
Problema de las n reinas Ejemplo.   N= 4.
Problema de las n reinas Evaluación de la eficiencia .  La evaluación es compleja, ya que el tiempo de ejecución en cada nodo no es constante y el número de nodos generado es difícil de predecir. El tiempo de ejecución de la función  Criterio  depende del nivel. Para nivel  i , el número de comprobaciones es (i-1). Está en O(i). Se puede hacer constante. Número de nodos, en el peor caso: Nivel 0: 1 Nivel 1: n/2 0·n/2 Comprobaciones Nivel 2: (n/2)(n-1) 1·(n/2)(n-1) “ .... Nivel n: n!/2 (n-1)·n!/2 “ La cota superior está muy alejada del número real de nodos generados. Ejemplo .  Para n = 4. Número de nodos en el peor caso = 33. Número de nodos generados realmente = 9.
Problema de las n reinas Además, en cada nodo (excepto en las hojas) se comprueban 4 posibles descendientes. Este es el número de veces que se ejecutan las funciones  Criterio  y  Genera   (s[nivel] = s[nivel] + 1) . Solución : Estimación de la eficiencia por probabilidad.  Hacemos un cálculo aproximado del número de nodos esperado. Estimación de la eficiencia por probabilidad . Generamos varias permutaciones de (1, 2, .., n), de forma aleatoria. Para cada una calcular el nivel al que llegaría (aplicando la función Criterio), y el número de nodos máximo para ese nivel. Hacer una media del número de nodos.
Problema :  maximizar    sujeto a   con x i = 0, 1 siendo  v i  = beneficio del objeto  i ;  w i  = peso de  i ;  M  capacidad máxima. Características  del problema: Es un problema de optimización (maximización). Sólo nos interesa una solución, la óptima. Existirá al menos una solución (no incluir ningún objeto). Diseño de la solución   con backtracking: Representación de la solución : Una solución será de la forma (x 1 , x 2 , ..., x n ), con x i = 0, 1. Se generará un árbol binario de soluciones. En cada nivel  i , probamos la posibilidad de incluir o no el objeto  i . Problema de la mochila 0/1 x 1 x 2 x 3 1 0 1 5 2 3 6 4 8 7 0 1 0 1 0 1 12 9 10 13 11 15 14 0 1 0 1 0 1
Problema de la mochila 0/1 Para calcular el peso y el beneficio en cada nodo podemos usar variables locales  w_act ,   v_act   que guardarán el peso y el beneficio acumulado. El array de soluciones será  s: array [1..n] of –1,0,1 . s[i] = 1, 0 . Se añade o no se añade el objeto i. s[i] = -1 . No se ha considerado el objeto i (es el valor de inicialización). Al ser un problema de optimización no acabamos hasta haber recorrido todos los nodos. Acabar cuando  nivel = 0  (volvemos al nodo raíz). En cada momento llevamos la mejor solución hasta un nodo. Si encontramos una solución nueva, comprobar si es mejor que la solución actual. Variable  v_max , con el valor de la mejor solución hasta este nodo y  s_max  con los objetos que la componen. si  Solución (nivel, s)     si v_act > v_max  v_max = v_act s_max = s
Problema de la mochila 0/1 Generar (nivel, s) . Probar los valores 0 y 1. Si s[nivel]=-1  Devolver 0 en otro caso  w_act = w_act + w[nivel]   v_act = v_act + v[nivel]   Devolver 1 Solución (nivel, s) . Indica los nodos hoja que cumplen la restricción de peso. Devolver (nivel=n) y (w_act    M) Criterio (nivel, s) . Indicará si se cumple la restricción de peso y no estamos en el último nivel. Devolver (nivel<n) y (w _act    M) MasHermanos (nivel, s) . Devolver s[nivel]    1 Retroceder (nivel, s) . w_act = w_act - s[nivel]*w[nivel] v_act = v_act - s[nivel]*v[nivel] s[nivel] = -1 nivel = nivel - 1
Problema de la mochila 0/1 Orden de complejidad del algoritmo : Número de nodos generado= 2 n+1 -1. El algoritmo es de O(2 n ). Problema : En el ejemplo, se generan todos los nodos posibles. La función  Criterio  es siempre cierta (excepto para algunos nodos hoja). Solución : Intentar eliminar algunos nodos del árbol de soluciones, con una función  Criterio  más restrictiva. Para cada nodo, hacer una estimación del máximo beneficio que se podría obtener a partir del mismo. Si es menor que el mayor beneficio de una solución anterior ( v_max ) entonces rechazar ese nodo y sus descendientes. La estimación del beneficio para el nivel y nodo actual será: v_estimado = v_act + Estimacion (k + 1, M - w_act) Estimacion (k, Q) : Estimar una cota superior para el problema de la mochila 0/1, usando los objetos  k..n , con capacidad máxima  Q .
Problema de la mochila 0/1 Idea :  el resultado del problema de la mochila (no 0/1) es una cota superior válida para el problema de la mochila 0/1. Estimacion (k, Q) : Aplicar el algoritmo voraz para el problema de la mochila, con los elementos de k..n. Si los beneficios son enteros, nos podemos quedar con la parte entera del resultado anterior. Ejemplo . n = 4; M = 7; v = (2, 3, 4, 5) w = (1, 2, 3, 4)
Problema de la mochila 0/1 Función Criterio (nivel, s, v_act, w_act, v_max). Si (w _act > M) o (nivel=n)    Devolver False en otro caso   v_estimado= v_act +   MochilaVoraz (nivel+1, M - w_act)    Devolver v_estimado > v_max Modificación  en el algoritmo de backtracking.   ... mientras no  MasHermanos (nivel, s)  o  no  Criterio (nivel, s, v_act, w_act, v_max)     Retroceder (nivel, s) ;   ... Se eliminan nodos a costa de aumentar el tiempo de ejecución de la función  Criterio . ¿Cuál será el tiempo de ejecución total?
Problema de la mochila 0/1 Suponemos todos los objetos ordenados por  v i /w i . Tiempo de la función  Criterio  en el nivel  i  (en el peor caso)  = 1  + Tiempo de la función  MochilaVoraz  = 1 + n - i . Idea intuitiva .  Tiempo en el peor caso (suponiendo todos los nodos): Número de nodos O(2 n ) * Tiempo de cada nodo (función criterio) O(n). ¿Tiempo: O(n·2 n )? Conclusiones : El cálculo “intuitivo” del tiempo no es correcto (no es válido O(n·2 n )). El orden de complejidad no varía, O(2 n ), aunque el tiempo es 2 veces mayor.  Si se podan más de la mitad de los nodos podemos esperar una mejora.
Problema de la mochila 0/1 Posible modificación 1 Para cada nodo, generar primero el valor 1 y luego el valor 0 (en lugar de primero 0 y luego 1). Ejemplo  anterior . Idea :  es de esperar que la solución de la mochila 0/1 sea “parecida” a la de la mochila no 0/1. Si ordenamos los objetos por v i /w i  entonces tendremos una solución con 1 en las primeras posiciones.
Problema de la mochila 0/1 Posible modificación 2 Utilizar una  representación  de la solución como un conjunto de los elementos incluidos. S = (s 1 , s 2 , ..., s m ) donde m  n y s i     {1, 2, ..., n}. ¿Cómo generar un árbol de este tipo? ¿Cuál es el número de nodos máximo? Árbol combinatorio

Más contenido relacionado

PPT
Modelo de datos
PDF
Manual estructura de_datos_2010___h._caselli_g
PPTX
Tipos de listas en estructura de datos
PPT
Modelo de Objeto Semantico
 
PDF
PDF
Estructura de Datos - árboles y grafos
PPTX
Base de Datos Orientada a Objetos
DOCX
Modelo entidad relacion(gestion de examenes)
Modelo de datos
Manual estructura de_datos_2010___h._caselli_g
Tipos de listas en estructura de datos
Modelo de Objeto Semantico
 
Estructura de Datos - árboles y grafos
Base de Datos Orientada a Objetos
Modelo entidad relacion(gestion de examenes)

La actualidad más candente (20)

PPTX
Unidad 6
PPTX
Modelo entidad relación de base de datos
PDF
Sesion12-componentes Visuales java
PDF
Casos de éxito de TSP en México
PPT
Ordenamiento ppt
PDF
Proceso unificado
PPTX
Unidad 1 introducción a las estructuras de datos
PPTX
Etapas en el diseño de Base de Datos
PPTX
Tema2 modelo entidad relación
PPTX
Modelador de base de datos ERwin
PDF
03 Modelo Relacional
ODT
Especificación de requisitos de software
PPT
Tm03 modelo de casos de uso
PPT
Vista lógica
PPTX
1. tipos de datos abstractos
PDF
PPTX
Transformacion de relaciones
PPT
Modelo Del Negocio con RUP y UML Parte 3
PPT
diagrama de casos de uso del negocio y del sistema
PPTX
Construcción de base de datos
Unidad 6
Modelo entidad relación de base de datos
Sesion12-componentes Visuales java
Casos de éxito de TSP en México
Ordenamiento ppt
Proceso unificado
Unidad 1 introducción a las estructuras de datos
Etapas en el diseño de Base de Datos
Tema2 modelo entidad relación
Modelador de base de datos ERwin
03 Modelo Relacional
Especificación de requisitos de software
Tm03 modelo de casos de uso
Vista lógica
1. tipos de datos abstractos
Transformacion de relaciones
Modelo Del Negocio con RUP y UML Parte 3
diagrama de casos de uso del negocio y del sistema
Construcción de base de datos
Publicidad

Destacado (9)

PPTX
Esquema algorítmico del backtracking
PPTX
Vuelta atrás o (backtracking)
PPTX
Algoritmo de backtracking
PDF
Backtracking
PPTX
Búsqueda en Anchura
PPT
busqueda a profundidad dsf
DOCX
Problema de asignación de programación dinámica
PDF
Simbolos diagrama de flujo
Esquema algorítmico del backtracking
Vuelta atrás o (backtracking)
Algoritmo de backtracking
Backtracking
Búsqueda en Anchura
busqueda a profundidad dsf
Problema de asignación de programación dinámica
Simbolos diagrama de flujo
Publicidad

Similar a Vuelta Atras (20)

PPT
PDF
Varios Algoritmos Voraces De DecisióN Y OptimizacióN
PPT
DOC
Plantillabasicas
PDF
Método simplex.
PPTX
metodos de optimizacion
PPTX
Programacion dinamica 22
PPTX
Algoritmo voraces
PPT
Programación Dinámica
DOCX
Metodo Simplex
PDF
Problemas de busqueda. (1).pdf
PDF
Algoritmos de vuelta atrás
DOC
resolucion de ecuaciones diferenciales con MATLAB
PPTX
Presentación de optimizacion
PPTX
Presentación de optimizacion
PPT
Divide y Venceras
PDF
Ecuacion De 1er Grado
PDF
representativa de suelo se realizo un ensayo con el permeámetro
PPT
Optimizacion
Varios Algoritmos Voraces De DecisióN Y OptimizacióN
Plantillabasicas
Método simplex.
metodos de optimizacion
Programacion dinamica 22
Algoritmo voraces
Programación Dinámica
Metodo Simplex
Problemas de busqueda. (1).pdf
Algoritmos de vuelta atrás
resolucion de ecuaciones diferenciales con MATLAB
Presentación de optimizacion
Presentación de optimizacion
Divide y Venceras
Ecuacion De 1er Grado
representativa de suelo se realizo un ensayo con el permeámetro
Optimizacion

Más de Salvador Fernández Fernández (20)

PDF
Servicio web soap en java con net beans
PDF
Ejemplo Base de Datos SQLite (Android)
PDF
PDF
Ejemplo de paso de funciones como parámetros a otra función
PDF
Ejemplo usopunteros
PDF
Solucion ejercicios punteros cadenas-vectores
PDF
Ejercicios punteros cadenas-vectores
PDF
Diagramas de flujo
PDF
Introducción a Enterprise Java Beans
PDF
Colorear fotografias en blanco y negro
PDF
10 mentiras con las que siempre engañan a los diseñadores gráficos por John Dani
PDF
10 mentiras con las que siempre engañan a los diseñadores gráficos por John Dani
PDF
PDF
Cableado Estructurado de Red
PDF
Redes De Computadores UOC
PDF
Fundamentos Divide Y Venceras
PDF
Divide y Vencerás
PDF
Java orientado a objetos
Servicio web soap en java con net beans
Ejemplo Base de Datos SQLite (Android)
Ejemplo de paso de funciones como parámetros a otra función
Ejemplo usopunteros
Solucion ejercicios punteros cadenas-vectores
Ejercicios punteros cadenas-vectores
Diagramas de flujo
Introducción a Enterprise Java Beans
Colorear fotografias en blanco y negro
10 mentiras con las que siempre engañan a los diseñadores gráficos por John Dani
10 mentiras con las que siempre engañan a los diseñadores gráficos por John Dani
Cableado Estructurado de Red
Redes De Computadores UOC
Fundamentos Divide Y Venceras
Divide y Vencerás
Java orientado a objetos

Vuelta Atras

  • 1. Vuelta atrás o Backtracking 1. Método general. 2. Análisis de tiempos de ejecución. 3. Ejemplos de aplicación. 3.1. Problema de las 8 reinas. 3.2. Problema de la mochila 0/1.
  • 2. Método general El backtracking (método de retroceso ó vuelta atrás ) es una técnica general de resolución de problemas, aplicable tanto a problemas de optimización , juegos y otros tipos. El backtracking realiza una búsqueda exhaustiva y sistemática en el espacio de soluciones. Por ello, suele resultar ineficiente. La solución de un problema de backtracking se puede expresar como una tupla (x 1 , x 2 , ..., x n ) , satisfaciendo unas restricciones P(x 1 , x 2 , ..., x n ) y tal vez optimizando una cierta función objetivo. En cada momento, el algoritmo se encontrará en un cierto nivel k , con una solución parcial (x 1 , ..., x k ) . Si se puede añadir un nuevo elemento a la solución x k+1 , se genera y se avanza al nivel k+1 .
  • 3. Método general Si no, se prueban otros valores de x k . Si no existe ningún valor posible por probar, entonces se retrocede al nivel anterior k-1 . Se sigue hasta que la solución parcial sea una solución completa del problema, o hasta que no queden más posibilidades. El resultado es equivalente a hacer un recorrido en profundidad en el árbol de soluciones. Sin embargo, este árbol es implícito , no se almacena en ningún lugar. Ejemplo . Dado un conjunto de números enteros {13, 11, 7}, encontrar si existe algún subconjunto cuya suma sea exactamente 20.
  • 4. Método general Posibilidad 1) Árbol binario: En cada nivel i decidir si el elemento i está o no en la solución. Representación de la solución: (x 1 , x 2 , x 3 ), donde x i = (0, 1). Cada nodo representa un paso del algoritmo, una solución parcial en cada momento dado. El árbol indica un orden de ejecución (recorrido en profundidad) pero no se almacena en ningún lugar. Una solución es un nodo hoja con valor de suma 20. Posible mejora : En cada nodo llevamos el valor de la suma hasta ese punto. Si el valor es mayor que 20: retroceder al nivel anterior. Árbol de soluciones 1 k=1 (13) k=2 (11) k=3 (7) 1 0 1 5 2 3 6 4 8 7 0 1 0 1 0 1 12 9 10 13 11 15 14 0 1 0 1 0 1 0 7 11 13 18 20 24 31 Sumas totales
  • 5. Método general Posibilidad 2) Árbol combinatorio: En cada nivel i decidir qué elemento se añade (1, 2 o 3). Representación de la solución (s 1 , ..., s m ), donde m  n y s i  {1, 2, 3}. Árbol de soluciones 2 Cada nodo es una posible solución. Será válida si la suma es 20. El recorrido es también en profundidad. Necesitamos funciones para generar los nodos, para descartar nodos y para saber si un nodo es solución. ¿Cómo será la eficiencia del algoritmo? Depende del número de nodos. k=1 k=2 k=3 1 3 2 3 5 4 3 3 2 7 6 3 31 2 1 8 0 13 11 20 18 7 24
  • 6. Método general Esquema general (sin recursividad) . Suponiendo que existe al menos una solución y que queremos obtener una cualquiera. Backtracking (var s: array [1.. Max_nivel] of tipo) nivel = 1 fin = false repetir s[nivel] = Generar (nivel, s) si Solución (nivel, s) fin = true en otro caso si Criterio (nivel, s) nivel = nivel + 1 en otro caso mientras no MasHermanos (nivel, s) Retroceder (nivel, s) hasta fin=true
  • 7. Método general Variables : s : Almacena la solución (un array, desde 1 hasta el nº máximo de niveles). nivel : Indica el nivel actual en el que se encuentra el algoritmo. fin : Valdrá true cuando hayamos encontrado alguna solución. Funciones : Generar (nivel, s) : Genera el siguiente hermano (o el primero) para el nivel actual. Devuelve el siguiente valor a añadir a la solución parcial actual (depende de la solución parcial y del nivel). Solución (nivel, s) : Comprueba si la solución (s[1], ..., s[nivel]) es una solución válida para el problema. Criterio (nivel, s) : Comprueba si a partir de (s[1], ..., s[nivel]) se puede alcanzar una solución válida, o si se puede mejorar la actual. En otro caso se rechazarán todos los descendientes.
  • 8. Método general Funciones : MasHermanos (nivel, s) : Devuelve verdad si hay más hermanos del nodo actual que todavía no han sido generados. Retroceder (nivel, s) : Retrocede un nivel en el árbol de soluciones. Disminuye en 1 el valor de nivel , y posiblemente tendrá que actualizar la solución actual, quitando los elementos retrocedidos. ¿Cómo serían estas funciones en los ejemplos anteriores? Otros posibles casos de problemas : 1) No está garantizado que exista una solución, puede existir alguna o no. 2) Queremos obtener todas las soluciones, no sólo una. 3) El problema es de optimización. De todas las soluciones posibles queremos aquella que maximice (o minimice) una función objetivo.
  • 9. Análisis de tiempos de ejecución El tiempo de ejecución depende del número de nodos generados y del tiempo requerido para cada nodo, que viene dado por el coste de las funciones. Suponiendo que una solución sea de la forma: (x 1 , x 2 , ..., x n ), en el peor caso se generarán todas las posibles combinaciones para cada x i . Si el número de posibles valores para cada x i es m i , entonces se generan: m 1 nodos en el nivel 1 m 1 ·m 2 nodos en el nivel 2 ... .... m 1 ·m 2 · ... ·m n nodos en el nivel n Ejemplo : para el problema de la suma de subconjuntos m i = 2. El número de nodos generados es: t(n) = 2 + 2 2 + 2 3 + ... + 2 n = 2 n+1 - 2 Ejemplo : calcular todas las permutaciones de (1, 2, ..., n). En el nivel 1 tenemos n posibilidades, en el nivel 2 n-1, ..., en el nivel n una posibilidad. t(n) = n + n·(n-1) + n·(n-1)·(n-2) + ... + n!  O(n!) En general tendremos tiempos con órdenes de complejidad factoriales o exponenciales.
  • 10. Problema de las n reinas Problema : Dado un tablero de ajedrez de tamaño nxn , encontrar una forma (o todas) de colocar n reinas, sin que ninguna de ellas pueda comerse a otra. Solución 1 : Probar todas las posiciones posibles y para cada una comprobar si es válida. Para tamaño 8: 4.426 1 165.368 posibilidades. Solución 2 : Colocar cada reina en cada fila. Una solución será un array de 1..8. Para cada reina se probarán cada una de las 8 columnas. Habrá que probar: 8 8 = 16 1 777.216 posibilidades. Solución 3 : No colocar dos reinas en una misma columna. La solución será una permutación de los números (1, 2, ..., 8): 8! = 40.320 posibilidad. Error : No se comprueba si la situación es correcta hasta el final.
  • 11. Problema de las n reinas Solución con backtracking. Características : Puede existir solución o no. No es un problema de optimización. Suponemos que buscamos todas las soluciones. Representación . Array solución: s : array [1..8] of 0..8. s[i] = j . La reina de la fila i está en la columna j . Recorrido con backtracking: En cada nivel i , probar las formas de colocar la reina de la fila i , desde la columna 1 hasta la 8. La posición será válida (podemos avanzar de nivel) si la reina i no está en la misma columna o diagonal que alguna de las reinas anteriores.
  • 12. Problema de las n reinas Funciones: Generar (nivel, s) . Probar primero la posición 1, luego la 2, ..., hasta la 8. MasHermanos (nivel, s) . Cierto si s[nivel] es menor que 8. Criterio (nivel, s) . Comprobar si la reina de la posición s[nivel] no se come a las anteriores (1, 2, ..., nivel-1). Solución (nivel, s) . Cierto si el nodo es una hoja (nivel = n) y se cumple Criterio. Retroceder (nivel, s) . Quitar la reina de la posición nivel. s[nivel]:= 0 (valor de inicialización).
  • 13. Problema de las n reinas NReinasBacktracking (var s: array [1.. n] of integer) nivel = 1 s[1] = 0 repetir s[nivel] = s[nivel] + 1 mientras (s[nivel]  n) y no Criterio (nivel, s) s[nivel] = s[nivel] + 1 si (nivel=n) y (s[nivel]  n) MostrarSolucion (s) en otro caso si (s[nivel]  n) nivel = nivel + 1 s[nivel] = 0 en otro caso nivel = nivel -1 hasta nivel = 0 Criterio (nivel: 0..n; s: array [1.. n] of integer) : boolean para i = 1,2,...,nivel-1 si (s[nivel]=s[i]) o |s[i] - s[nivel]| = |i - nivel| Devolver false Devolver true
  • 14. Problema de las n reinas Ejemplo. N= 4.
  • 15. Problema de las n reinas Evaluación de la eficiencia . La evaluación es compleja, ya que el tiempo de ejecución en cada nodo no es constante y el número de nodos generado es difícil de predecir. El tiempo de ejecución de la función Criterio depende del nivel. Para nivel i , el número de comprobaciones es (i-1). Está en O(i). Se puede hacer constante. Número de nodos, en el peor caso: Nivel 0: 1 Nivel 1: n/2 0·n/2 Comprobaciones Nivel 2: (n/2)(n-1) 1·(n/2)(n-1) “ .... Nivel n: n!/2 (n-1)·n!/2 “ La cota superior está muy alejada del número real de nodos generados. Ejemplo . Para n = 4. Número de nodos en el peor caso = 33. Número de nodos generados realmente = 9.
  • 16. Problema de las n reinas Además, en cada nodo (excepto en las hojas) se comprueban 4 posibles descendientes. Este es el número de veces que se ejecutan las funciones Criterio y Genera (s[nivel] = s[nivel] + 1) . Solución : Estimación de la eficiencia por probabilidad. Hacemos un cálculo aproximado del número de nodos esperado. Estimación de la eficiencia por probabilidad . Generamos varias permutaciones de (1, 2, .., n), de forma aleatoria. Para cada una calcular el nivel al que llegaría (aplicando la función Criterio), y el número de nodos máximo para ese nivel. Hacer una media del número de nodos.
  • 17. Problema : maximizar sujeto a con x i = 0, 1 siendo v i = beneficio del objeto i ; w i = peso de i ; M capacidad máxima. Características del problema: Es un problema de optimización (maximización). Sólo nos interesa una solución, la óptima. Existirá al menos una solución (no incluir ningún objeto). Diseño de la solución con backtracking: Representación de la solución : Una solución será de la forma (x 1 , x 2 , ..., x n ), con x i = 0, 1. Se generará un árbol binario de soluciones. En cada nivel i , probamos la posibilidad de incluir o no el objeto i . Problema de la mochila 0/1 x 1 x 2 x 3 1 0 1 5 2 3 6 4 8 7 0 1 0 1 0 1 12 9 10 13 11 15 14 0 1 0 1 0 1
  • 18. Problema de la mochila 0/1 Para calcular el peso y el beneficio en cada nodo podemos usar variables locales w_act , v_act que guardarán el peso y el beneficio acumulado. El array de soluciones será s: array [1..n] of –1,0,1 . s[i] = 1, 0 . Se añade o no se añade el objeto i. s[i] = -1 . No se ha considerado el objeto i (es el valor de inicialización). Al ser un problema de optimización no acabamos hasta haber recorrido todos los nodos. Acabar cuando nivel = 0 (volvemos al nodo raíz). En cada momento llevamos la mejor solución hasta un nodo. Si encontramos una solución nueva, comprobar si es mejor que la solución actual. Variable v_max , con el valor de la mejor solución hasta este nodo y s_max con los objetos que la componen. si Solución (nivel, s) si v_act > v_max v_max = v_act s_max = s
  • 19. Problema de la mochila 0/1 Generar (nivel, s) . Probar los valores 0 y 1. Si s[nivel]=-1 Devolver 0 en otro caso w_act = w_act + w[nivel] v_act = v_act + v[nivel] Devolver 1 Solución (nivel, s) . Indica los nodos hoja que cumplen la restricción de peso. Devolver (nivel=n) y (w_act  M) Criterio (nivel, s) . Indicará si se cumple la restricción de peso y no estamos en el último nivel. Devolver (nivel<n) y (w _act  M) MasHermanos (nivel, s) . Devolver s[nivel]  1 Retroceder (nivel, s) . w_act = w_act - s[nivel]*w[nivel] v_act = v_act - s[nivel]*v[nivel] s[nivel] = -1 nivel = nivel - 1
  • 20. Problema de la mochila 0/1 Orden de complejidad del algoritmo : Número de nodos generado= 2 n+1 -1. El algoritmo es de O(2 n ). Problema : En el ejemplo, se generan todos los nodos posibles. La función Criterio es siempre cierta (excepto para algunos nodos hoja). Solución : Intentar eliminar algunos nodos del árbol de soluciones, con una función Criterio más restrictiva. Para cada nodo, hacer una estimación del máximo beneficio que se podría obtener a partir del mismo. Si es menor que el mayor beneficio de una solución anterior ( v_max ) entonces rechazar ese nodo y sus descendientes. La estimación del beneficio para el nivel y nodo actual será: v_estimado = v_act + Estimacion (k + 1, M - w_act) Estimacion (k, Q) : Estimar una cota superior para el problema de la mochila 0/1, usando los objetos k..n , con capacidad máxima Q .
  • 21. Problema de la mochila 0/1 Idea : el resultado del problema de la mochila (no 0/1) es una cota superior válida para el problema de la mochila 0/1. Estimacion (k, Q) : Aplicar el algoritmo voraz para el problema de la mochila, con los elementos de k..n. Si los beneficios son enteros, nos podemos quedar con la parte entera del resultado anterior. Ejemplo . n = 4; M = 7; v = (2, 3, 4, 5) w = (1, 2, 3, 4)
  • 22. Problema de la mochila 0/1 Función Criterio (nivel, s, v_act, w_act, v_max). Si (w _act > M) o (nivel=n) Devolver False en otro caso v_estimado= v_act +  MochilaVoraz (nivel+1, M - w_act)  Devolver v_estimado > v_max Modificación en el algoritmo de backtracking. ... mientras no MasHermanos (nivel, s) o no Criterio (nivel, s, v_act, w_act, v_max) Retroceder (nivel, s) ; ... Se eliminan nodos a costa de aumentar el tiempo de ejecución de la función Criterio . ¿Cuál será el tiempo de ejecución total?
  • 23. Problema de la mochila 0/1 Suponemos todos los objetos ordenados por v i /w i . Tiempo de la función Criterio en el nivel i (en el peor caso) = 1 + Tiempo de la función MochilaVoraz = 1 + n - i . Idea intuitiva . Tiempo en el peor caso (suponiendo todos los nodos): Número de nodos O(2 n ) * Tiempo de cada nodo (función criterio) O(n). ¿Tiempo: O(n·2 n )? Conclusiones : El cálculo “intuitivo” del tiempo no es correcto (no es válido O(n·2 n )). El orden de complejidad no varía, O(2 n ), aunque el tiempo es 2 veces mayor. Si se podan más de la mitad de los nodos podemos esperar una mejora.
  • 24. Problema de la mochila 0/1 Posible modificación 1 Para cada nodo, generar primero el valor 1 y luego el valor 0 (en lugar de primero 0 y luego 1). Ejemplo anterior . Idea : es de esperar que la solución de la mochila 0/1 sea “parecida” a la de la mochila no 0/1. Si ordenamos los objetos por v i /w i entonces tendremos una solución con 1 en las primeras posiciones.
  • 25. Problema de la mochila 0/1 Posible modificación 2 Utilizar una representación de la solución como un conjunto de los elementos incluidos. S = (s 1 , s 2 , ..., s m ) donde m  n y s i  {1, 2, ..., n}. ¿Cómo generar un árbol de este tipo? ¿Cuál es el número de nodos máximo? Árbol combinatorio