Manual DOSBox 0.74
Manual DOSBox 0.74
Manual DOSBox 0.74
Tema 5. Backtracking
5.1. Método general
5.2. Análisis de tiempos de ejecución
5.3. Ejemplos de aplicación
5.3.1. Problema de la mochila 0/1
5.3.2. Problema de la asignación
5.3.3. Resolución de juegos
A.E.D. 1
Tema 5. Backtracking
5.1. Método general
• El backtracking (o método de retroceso o vuelta
atrás) es una técnica general de resolución de
problemas, aplicable en 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 muy ineficiente.
• Se puede entender como “opuesto” a avance rápido:
– Avance rápido: añadir elementos a la solución y no
deshacer ninguna decisión tomada.
– Backtracking: añadir y quitar todos los elementos.
Probar todas las combinaciones.
A.E.D. 2
Tema 5. Backtracking
5.1. Método general
• Una solución se puede expresar como una tupla,
(x1, x2, ..., xn), que satisfaga unas restricciones y tal vez
que optimice cierta función objetivo.
• En cada momento, el algoritmo se encontrará en cierto
nivel k, con una solución parcial (x1, ..., xk).
– Si se puede añadir un nuevo elemento a la solución xk+1,
se genera y se avanza al nivel k+1.
– Si no, se prueban otros valores para xk.
– 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 por probar.
A.E.D. 3
Tema 5. Backtracking
5.1. Método general
• El resultado es equivalente a hacer un recorrido en
profundidad en el árbol de soluciones.
Inicio
x1=0 x1=1
A.E.D. 4
Tema 5. Backtracking
5.1. Método general
• Representación simplificada del árbol.
x1 1
0 1
2 9
x2 0 1
1 0
3 6 10 13
x3
0 1 0 1 0 1 0 1
4 5 7 8 11 12 14 15
A.E.D. 5
Tema 5. Backtracking
5.1. Método general
• Árboles de backtracking:
– El árbol es simplemente una forma de representar la
ejecución del algoritmo.
– Es implícito, no almacenado (no necesariamente).
– El recorrido es en profundidad, normalmente de
izquierda a derecha.
– La primera decisión para aplicar backtracking: ¿cómo
es la forma del árbol?
– Preguntas relacionadas: ¿Qué significa cada valor
de la tupla solución (x1, ..., xn)? ¿Cómo es la
representación de la solución al problema?
A.E.D. 6
Tema 5. Backtracking
5.1. Método general
• Tipos comunes de árboles de backtracking:
– Árboles binarios
– Árboles k-arios
– Árboles permutacionales
– Árboles combinatorios
A.E.D. 7
Tema 5. Backtracking
5.1. Método general
• Árboles binarios: s= (x1, x2, ..., xn), con xi {0, 1}
x1 1
0 1
2 5
x2 0 1 0 1
3 4 6 7
1
x1
1 2 3
2 6 10
x2 1 1 3 3
2 3 2 1 2
3 4 5 7 8 9 11 12 13
3 5 7 9 12 14
3 2 3 1 2 1 x3
4 6 8 10 13 15
A.E.D. 14
Tema 5. Backtracking
5.1. Método general
• Funciones:
– Criterio (nivel, s): comprueba si a partir de (s[1]...
s[nivel]) se puede alcanzar una solución válida. En otro
caso se rechazarán todos los descendientes (poda).
– MasHermanos (nivel, s): devuelve true 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.
• Además, suele ser común utilizar variables temporales
con el valor actual (beneficio, peso, etc.) de la tupla
solución.
A.E.D. 15
Tema 5. Backtracking
5.1. Método general
• Ejemplo de problema: encontrar un subconjunto del
conjunto T= {t1, t2, ..., tn} que sume exactamente P.
• Variables:
– Representación de la solución con un árbol binario.
– s: array [1..n] de {-1, 0, 1}
• s[i] = 0 el número i-ésimo no se utiliza
• s[i] = 1 el número i-ésimo sí se utiliza
• s[i] = -1 valor de inicialización (número i-ésimo
no estudiado)
– sINICIAL: (-1, -1, ..., -1)
– fin: valdrá true cuando se haya encontrado solución.
– tact: suma acumulada hasta ahora (inicialmente 0).
A.E.D. 16
Tema 5. Backtracking
5.1. Método general
Funciones:
• Generar (nivel, s)
s[nivel]:= s[nivel] + 1
si s[nivel] == 1 entonces tact:= tact + tnivel
• Solución (nivel, s)
devolver (nivel == n) Y (tact == P)
• Criterio (nivel, s)
devolver (nivel < n) Y (tact ≤ P)
• MasHermanos (nivel, s)
devolver s[nivel] < 1
• Retroceder (nivel, s)
tact:= tact – tnivel*s[nivel]
s[nivel]:= -1
nivel:= nivel – 1
A.E.D. 17
Tema 5. Backtracking
5.1. Método general
• Algoritmo: ¡el mismo que el esquema general!
Backtracking (var s: TuplaSolución)
nivel:= 1
s:= sINICIAL
fin:= false
repetir
Generar (nivel, s)
si Solución (nivel, s) entonces
fin:= true
sino si Criterio (nivel, s) entonces
nivel:= nivel + 1
sino
mientras NOT MasHermanos (nivel, s) hacer
Retroceder (nivel, s)
finsi
hasta fin
A.E.D. 18
Tema 5. Backtracking
5.1. Método general
A.E.D. 19
Tema 5. Backtracking
5.1. Método general
• Caso 1) Puede que no exista ninguna solución.
Backtracking (var s: TuplaSolución)
nivel:= 1
s:= sINICIAL
fin:= false Para poder generar
repetir todo el árbol de
Generar (nivel, s) backtracking
si Solución (nivel, s) entonces
fin:= true
sino si Criterio (nivel, s) entonces
nivel:= nivel + 1
sino
mientras NOT MasHermanos (nivel, s) AND (nivel>0)
hacer Retroceder (nivel, s)
finsi
hasta fin
fin OR (nivel==0)
A.E.D. 20
Tema 5. Backtracking
5.1. Método general
• Caso 2) Queremos almacenar todas las soluciones.
Backtracking (var s: TuplaSolución)
nivel:= 1 • En algunos problemas los nodos
s:= sINICIAL
intermedios pueden ser soluciones
fin:= false
repetir • O bien, retroceder después de
Generar (nivel, s) encontrar una solución
si Solución (nivel, s) entonces
Almacenar
fin:= true (nivel, s)
si Criterio
sino (nivel,(nivel,
si Criterio s) entonces
s) entonces
nivel:= nivel + 1
sino
mientras NOT MasHermanos (nivel, s) AND (nivel>0)
hacer Retroceder (nivel, s)
finsi
hasta fin
nivel==0
A.E.D. 21
Tema 5. Backtracking
5.1. Método general
• Caso 3) Problema de optimización (maximización).
Backtracking (var s: TuplaSolución)
nivel:= 1 voa: valor óptimo actual
s:= sINICIAL
fin:=
voa:=false
-; soa:= Ø soa: solución óptima actual
repetir
Generar (nivel, s)
AND Valor(s) > voa entonces
si Solución (nivel, s) entonces
fin:=
voa:= true
Valor(s); soa:= s
si Criterio
sino (nivel,(nivel,
si Criterio s) entonces
s) entonces
nivel:= nivel + 1
sino
mientras NOT MasHermanos (nivel, s) AND (nivel>0)
hacer Retroceder (nivel, s)
finsi
hasta fin
nivel==0
A.E.D. 22
Tema 5. Backtracking
5.1. Método general
• Ejemplo de problema: encontrar un subconjunto del
conjunto T= {t1, t2, ..., tn} que sume exactamente P,
usando el menor número posible de elementos.
• Funciones:
– Valor(s)
devolver s[1] + s[2] + ... + s[n]
– ¡Todo lo demás no cambia!
• Otra posibilidad: incluir una nueva variable:
vact: entero. Número de elementos en la tupla actual.
– Inicialización (añadir): vact:= 0
– Generar (añadir): vact:= vact + s[nivel]
– Retroceder (añadir): vact:= vact – s[nivel]
A.E.D. 23
Tema 5. Backtracking
5.2. Análisis de tiempos de ejecución
• Normalmente, el tiempo de ejecución se puede obtener
multiplicando dos factores:
– Número de nodos del árbol (generados).
– Tiempo de ejecución de cada nodo.
...siempre que el tiempo en cada nodo sea del mismo orden.
• Formulación matemática:
Maximizar xi bi; sujeto a la restricción xi pi ≤ M, y xi{0,1}
i=1..n i=1..n
A.E.D. 25
Tema 5. Backtracking
5.3.1. Problema de la mochila 0/1
• Ejemplo: n = 4; M = 7
b = (2, 3, 4, 5)
p = (1, 2, 3, 4) 4 kg
3 kg
7 Kg. 2 kg
100 Kg.
1 kg
PVP 2 PVP 190
A.E.D. 28
Tema 5. Backtracking
5.3.1. Problema de la mochila 0/1
1) Representación de la solución.
• Con un árbol binario: s= (x1, x2, ..., xn), con xi {0,1}
– xi = 0 No se coge el objeto i
– xi = 1 Sí se coge el objeto i
– xi = -1 Objeto i no estudiado
– En el nivel i se 1 x1
0 1
estudia el objeto i
– Las soluciones 2 9
0 0 1 x2
están en nivel n 1
3 6 10 13
x3
0 0 0 1 1
1 1 0
4 5 7 8 11 12 14 15
A.E.D. 29
Tema 5. Backtracking
5.3.1. Problema de la mochila 0/1
1) Representación de la solución.
• También es posible usar un árbol combinatorio:
s= (x1, x2, ..., xm), con m ≤ n, xi {1,..,n} y xi < xi+1
– xi Número de objeto escogido
– m Número total de objetos escogidos
– Las soluciones están en cualquier nivel
1
1 3 x1
2
2 6 8
2 3
3 x2
3 5 7
3
x3
4
A.E.D. 30
Tema 5. Backtracking
5.3.1. Problema de la mochila 0/1
2) Elegir el esquema de algoritmo: caso optimización.
Consejo: no reinventar la rueda.
Backtracking (var s: array [1..n] de entero)
nivel:= 1; s:= sINICIAL
voa:= -; soa:= Ø pact: Peso actual
pact:= 0; bact:= 0 bact: Beneficio actual
repetir
Generar (nivel, s)
si Solución (nivel, s) AND (bact > voa) entonces
voa:= bact; soa:= s
si Criterio (nivel, s) entonces
nivel:= nivel + 1
sino
mientras NOT MasHermanos (nivel, s) AND (nivel>0)
hacer Retroceder (nivel, s)
finsi
hasta nivel == 0
A.E.D. 31
Tema 5. Backtracking
5.3.1. Problema de la mochila 0/1
3) Funciones genéricas del esquema.
• Generar (nivel, s) Probar primero 0 y luego 1
s[nivel]:= s[nivel] + 1 si s[nivel]==1 entonces
pact:= pact + p[nivel]*s[nivel] pact:= pact + p[nivel]
bact:= bact + b[nivel]*s[nivel] bact:= bact + b[nivel]
• Solución (nivel, s) finsi
devolver (nivel==n) AND (pact≤M)
• Criterio (nivel, s)
devolver (nivel<n) AND (pact≤M)
• MasHermanos (nivel, s)
devolver s[nivel] < 1
• Retroceder (nivel, s)
pact:= pact – p[nivel]*s[nivel]
bact:= bact – b[nivel]*s[nivel]
s[nivel]:= -1
nivel:= nivel – 1
A.E.D. 32
Tema 5. Backtracking
5.3.1. Problema de la mochila 0/1
• Ejemplo: n = 4; M = 7; b = (2, 3, 4, 5); p = (1, 2, 3, 4)
1
0 1 x1
2 17
0 1 x2
1 0
3 10 18 25
x3
0 0 0 1 1
1 1 0
4 7 11 14 19 22 26 29
0 1 1 1 x4
0 1 0 1 0 1 0 1 0 1 0 0
5 6 8 9 12 13 15 16 20 21 23 24 27 28 30 31
pact: 0 4 7 9 8 7 10
bact: 0 5 9 12
A.E.D.
11 10 33 14
Tema 5. Backtracking
5.3.1. Problema de la mochila 0/1
• El algoritmo resuelve el problema, encontrando la solución
óptima pero...
• Es muy ineficiente. ¿Cuánto es el orden de complejidad?
• Problema adicional: en el ejemplo, se generan todos los
nodos posibles, no hay ninguna poda. La función Criterio es
siempre cierta (excepto para algunos nodos hoja).
• Solución: mejorar la poda con una función Criterio más
restrictiva.
• Incluir una poda según el criterio de optimización.
– Poda según el criterio de peso: si el peso actual es
mayor que M podar el nodo.
– Poda según el criterio de optimización: si el beneficio
actual no puede mejorar el voa podar el nodo.
A.E.D. 34
Tema 5. Backtracking
5.3.1. Problema de la mochila 0/1
• ¿Cómo calcular una cota superior del beneficio que se puede
obtener a partir del nodo actual, es decir (x1, ..., xk)?
• La estimación debe poder realizarse de forma rápida.
0 1 1 x1
2 9
0 0 x2
1
s= (1, 0)
10 pact= x
................ bact= y
bestimado= ¿?
¿?
0/0/9 2 10 1/2/10
0 0 1 x2
3 7 3 7
5 0 6 4 8 4 9 9 14 5 15 10
0 5
voa:0 5 9 10
A.E.D. 38
Tema 5. Backtracking
5.3.1. Problema de la mochila 0/1
• Se eliminan nodos pero... a costa de aumentar el tiempo de
ejecución en cada nodo.
• ¿Cuál será el tiempo de ejecución total?
• Suponiendo los objetos ordenados por bi/pi...
• 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(2n) * tiempo de cada nodo
(función criterio) O(n).
• ¿Tiempo: O(n·2n)? NO
n n n
t (n ) 2 (n i 1) (n 1) 2 i 2i 2·2 n 1 2n 4
i i
i 1 i 1 i 1
A.E.D. 39
Tema 5. Backtracking
5.3.1. Problema de la mochila 0/1
Conclusiones:
• El cálculo intuitivo no es correcto.
• En el peor caso, el orden de complejidad sigue siendo un
O(2n).
• En promedio se espera que la poda elimine muchos nodos,
reduciendo el tiempo total.
• Pero el tiempo sigue siendo muy malo. ¿Cómo mejorarlo?
• Posibilidades:
– Generar primero el 1 y luego el 0.
– Usar un árbol combinatorio.
– ...
A.E.D. 40
Tema 5. Backtracking
5.3.1. Problema de la mochila 0/1
• Modificación: generar primero el 1 y luego el 0.
• Ejercicio: cambiar las funciones Generar y MasHermanos.
• Ejemplo: n = 4; M = 7
b = (2, 3, 4, 5) 1 1 0/0/10
p = (1, 2, 3, 4) x1
1/2/10
2
1
x2
3/5/10 3
1 0 x3
6/9/10 4 7 3/5/10
1 0 1 x4
10 6 7
5 14 6 9 8 10
voa: 9 10
A.E.D. 41
Tema 5. Backtracking
5.3.1. Problema de la mochila 0/1
• En este caso es mejor la estrategia “primero el 1”, pero
¿y en general?
• Si la solución óptima es de la forma s = (1, 1, 1, X, X, 0,
0, 0) entonces se alcanza antes la solución generando
primero 1 (y luego 0).
• Si es de la forma s = (0, 0, 0, X, X, 1, 1, 1) será mejor
empezar por 0.
• 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 bi/pi entonces tendremos una solución
del primer tipo.
A.E.D. 42
Tema 5. Backtracking
5.3.1. Problema de la mochila 0/1
• Modificación: usar un árbol combinatorio.
• Representación de la solución:
s= (x1, x2, ..., xm), con m ≤ n, xi {1,..,n} y xi < xi+1
– xi Número de objeto escogido 1
– m Número total de 1 3 x1
2
objetos escogidos 2 6 8
– Las soluciones 2 3 3 x2
están en
3 5 7
cualquier nivel 3
x3
4
1 4 9 1
2 7 2 3 Ejemplo 2. (P1, T2),
(P2, T1), (P3, T3)
3 6 3 5
BTOTAL= 9+7+5= 21
A.E.D. 45
Tema 5. Backtracking
5.3.2. Problema de asignación
• El problema de asignación es un problema NP-
completo clásico.
• Otras variantes y enunciados:
– Problema de los matrimonios estables.
– Problemas con distinto número de tareas y personas.
Ejemplo: problema de los árbitros.
– Problemas de asignación de recursos: fuentes de
oferta y de demanda. Cada fuente de oferta tiene una
capacidad O[i] y cada fuente de demanda una D[j].
– Isomorfismo de grafos: la matriz de pesos varía
según la asignación realizada.
A.E.D. 46
Tema 5. Backtracking
5.3.2. Problema de asignación
Enunciado del problema de asignación
• Datos del problema:
– n: número de personas y de tareas disponibles.
– B: array [1..n, 1..n] de entero. Rendimiento o beneficio
de cada asignación. B[i, j] = beneficio de asignar a la
persona i la tarea j.
• Resultado:
– Realizar n asignaciones {(p1, t1), (p2, t2), ..., (pn, tn)}.
• Formulación matemática:
Maximizar B[pi, tj], sujeto a la restricción pi≠pj, ti≠tj, i≠j
i=1..n
proceso
A.E.D. 47
Tema 5. Backtracking
5.3.2. Problema de asignación
1) Representación de la solución
• Mediante pares de asignaciones: s = {(p1, t1), (p2, t2), ...,
(pn, tn)}, con pi≠pj, ti≠tj, i≠j
– La tarea ti es asignada a la persona pi.
– Árbol muy ancho. Hay que garantizar muchas
restricciones. Representación no muy buena.
• Mediante matriz de asignaciones: s = ((a11, a12, ..., a1n),
(a21, a22, ..., a2n), ..., (an1, an2, ..., ann)), con aij {0, 1}, y con
i=1..n aij = 1, j=1..n aij = 1. Tareas
– aij = 1 la tarea j se asigna a 1 2 3
Personas
a la persona i 1 0 1 0
– aij = 0 la tarea j no se
2 1 0 0
asigna a la persona i
3 0 0 1
A.E.D. 48
Tema 5. Backtracking
5.3.2. Problema de asignación
1) Representación de la solución
• Mediante matriz de asignaciones.
– Árbol binario, pero muy profundo: n2 niveles en el árbol.
– También tiene muchas restricciones.
• Desde el punto de vista de las personas: s = (t1, t2, ..., tn),
siendo ti {1, ..., n}, con ti≠tj, i≠j
– ti número de tarea asignada a la persona i.
– Da lugar a un árbol permutacional. ¿Cuál es el número
de nodos?
• Desde el punto de vista de las tareas: s = (p1, p2, ..., pn),
siendo pi {1, ..., n}, con pi≠pj, i≠j
– pi número de persona asignada a la tarea i.
– Representación análoga (dual) a la anterior.
A.E.D. 49
Tema 5. Backtracking
5.3.2. Problema de asignación
2) Elegir el esquema de algoritmo: caso optimización.
Backtracking (var s: array [1..n] de entero)
nivel:= 1; s:= sINICIAL
voa:= -; soa:= Ø bact: Beneficio actual
bact:= 0
repetir
Generar (nivel, s)
si Solución (nivel, s) AND (bact > voa) entonces
voa:= bact; soa:= s
si Criterio (nivel, s) entonces
nivel:= nivel + 1
sino
mientras NOT MasHermanos (nivel, s) AND (nivel>0)
hacer Retroceder (nivel, s)
finsi
hasta nivel == 0
A.E.D. 50
Tema 5. Backtracking
5.3.2. Problema de asignación
3) Funciones genéricas del esquema.
• Variables:
– s: array [1..n] de entero: cada s[i] indica la tarea asignada
a la persona i. Inicializada a 0.
– bact: beneficio de la solución actual
• Criterio (nivel, s)
para i:= 1, ..., nivel-1 hacer
si s[nivel] == s[i] entonces devolver false
finpara
devolver true
A.E.D. 51
Tema 5. Backtracking
5.3.2. Problema de asignación
3) Funciones genéricas del esquema.
• Solución (nivel, s)
devolver (nivel==n) AND Criterio (nivel, s)
• MasHermanos (nivel, s)
devolver s[nivel] < n
• Retroceder (nivel, s)
bact:= bact – B[nivel, s[nivel]]
s[nivel]:= 0
nivel:= nivel – 1
A.E.D. 52
Tema 5. Backtracking
5.3.2. Problema de asignación Tareas
• Ejemplo de aplicación. n = 3 B 1 2 3
Personas
1 4 9 1
2 7 2 3
(bact= 0) 1
t1 3 3 6 3 5
1
2
(4) 2 (9) 6 (1) 11
t2 2 3 1 3 1 2
(16)
(6) 3 (7) 5 7 (12) 9 12 (8) 14 (3)
t3 3 2 3 1 2 1
(21)
(11) 4 (10) 6 8 (18) 10 13 (11) 15 (9)
voa: 11 21
A.E.D. 53
Tema 5. Backtracking
5.3.2. Problema de asignación
• ¿Cuál es el orden de complejidad del algoritmo?
A.E.D. 54
Tema 5. Backtracking
5.3.2. Problema de asignación
3) Funciones genéricas del esquema.
• Criterio (nivel, s)
si usadas[s[nivel]] entonces
devolver false
O bien hacerlo antes de la
sino
usadas[s[nivel]]:= true instrucción:
devolver true nivel:= nivel + 1
finsi
• Solución (nivel, s)
devolver (nivel==n) AND NOT usadas[s[nivel]]
• Retroceder (nivel, s)
bact:= bact – B[nivel, s[nivel]]
usadas[s[nivel]]:= false
s[nivel]:= 0
nivel:= nivel – 1
A.E.D. 55
Tema 5. Backtracking
5.3.2. Problema de asignación
3) Funciones genéricas del esquema.
• Las funciones Generar y MasHermanos no se modifican.
• Conclusiones:
– El algoritmo sigue siendo muy ineficiente.
– Aunque garantiza la solución óptima...
– ¿Cómo mejorar el tiempo?
– Aplicar una poda según el criterio de optimización...
A.E.D. 56
Tema 5. Backtracking
5. Conclusiones
• Backtracking: recorrido exhaustivo y sistemático en un
árbol de soluciones.
• Pasos para aplicarlo:
– Decidir la forma del árbol.
– Establecer el esquema del algoritmo.
– Diseñar las funciones genéricas del esquema.
• Relativamente fácil diseñar algoritmos que encuentren
soluciones óptimas pero...
• Los algoritmos de backtracking son muy ineficientes.
A.E.D. 57
Tema 5. Backtracking