Tema 7: Algoritmos de vuelta atrás 7.1 7.2 7.3 7.4 7.5 Introducción Esquema general Colocación de Reinas en un tablero Recorrido del Rey en ajedrez La mochila (4 versiones) 1 Esquema general una solución (I) func btUna(x: Etapa) dev (exito: Logico) var xsig: Etapa cand: Candidatos alg si esSolucion(x): exito := cierto | otras: exito := falso cand := calculaCandidatos(x) mientras NO exito Y quedanCandidatos(cand) xsig = seleccionaCandidato(cand, x) si esPrometedor(cand, x, xsig): anotaSolucion(cand, x, xsig) exito := btUna(xsig) si NO exito: cancelaAnotacion(cand, x, xsig) fsi fsi fmientras fsi fin 2 Esquema general una solución (II) <abstracto> <abstracto> <abstracto> <abstracto> <abstracto> <abstracto> <abstracto> func esSolucion(x: Etapa) dev (b: Logico) func calculaCandidatos(x: Etapa) dev (cand: Candidatos) func quedanCandidatos(cand: Candidatos) dev (b: Logico) func seleccionaCandidato(cand: Candidatos; ent/sal x: Etapa) dev (xsig: Etapa) func esPrometedor(cand:Candidatos; x, xsig: Etapa) dev (b: Logico) proc anotaSolucion(cand:Candidatos; ent/sal x, xsig: Etapa) proc cancelaAnotacion(cand: Candidatos; ent/sal x, xsig: Etapa) 3 Esquema general todas soluciones proc btTodas(x: Etapa) var xsig: Etapa cand: Candidatos alg si esSolucion(x): comunicaSolucion() fsi cand := calculaCandidatos(x) mientras quedanCandidatos(cand) xsig := seleccionaCandidato(cand, x) si esPrometedor(cand, x, xsig): anotaSolucion(cand, x, xsig) btTodas(xsig) cancelaAnotacion(cand, x, xsig) fsi fmientras fin <abstracto> proc comunicaSolucion() 4 Esquema general solución óptima proc btOptimo(x: Etapa) var xsig: Etapa cand: Candidatos alg si esSolucion(x): si esMejor(): actualizaSolucion() fsi fsi cand := calculaCandidatos(x) mientras quedanCandidatos(cand) xsig = seleccionaCandidato(cand, x) si esPrometedor(cand, x, xsig): anotaSolucion(cand, x, xsig) btOptimo(xsig) cancelaAnotacion(cand, x, xsig) fsi fmientras fin <abstracto> func esMejor() dev (b:Logico) <abstracto> proc actualizaSolucion() 5 Colocar Reinas en tablero – Una (1) clase ReinasBT_UNA N: Entero sol: Solucion clase Solucion s: array [1..N] de Entero fclase clase Etapa k: Entero fclase clase Candidatos i: Entero fclase func colocaReinas() dev (exito: Logico) var x: Etapa alg x.k := 0 //no haría falta, solo que esté creado el array sol.s := < crea array de ceros > exito := btUna(x) si exito: <tratar sol> fsi fin func esSolucion(x: Etapa) dev (b: Logico) alg b := (x.k = N) fin 6 Colocar Reinas en tablero – Una (2) func calculaCandidatos(x: Etapa) dev (cand: Candidatos) alg // los candidatos son los enteros desde 1 a N cand.i := 0 fin func quedanCandidatos(cand: Candidatos) dev (b: Logico) alg b := (cand.i < N) fin func btUna(x: Etapa) dev (exito: Logico) var xsig: Etapa cand: Candidatos alg si esSolucion(x): exito := cierto | otras: exito := falso cand := calculaCandidatos(x) mientras NO exito Y quedanCandidatos(cand) xsig := seleccionaCandidato(cand, x) si esPrometedor(cand, x, xsig): anotaSolucion(cand, x, xsig) exito := btUna(xsig) si NO exito: cancelaAnotacion(cand, x, xsig) fsi fsi fmientras fsi fin func seleccionaCandidato (ent/sal cand: Candidatos; ent/sal x: Etapa) dev (xsig: Etapa) alg cand.i := cand.i + 1 xsig.k := x.k + 1 fin 7 Colocar Reinas en tablero – Una (3) func esPrometedor(cand:Candidatos; x, xsig: Etapa) dev (b: Logico) var func btUna(x: Etapa) dev (exito: Logico) i: Entero var alg // sol es (x.k)-prometedor xsig: Etapa cand: Candidatos <b, i> := <cierto, 1> alg mientras (i <= xsig.k - 1) Y (b) si esSolucion(x): exito := cierto si (sol.s[i] = cand.i) O (Abs(sol.s[i]-cand.i) = Abs(i-xsig.k)): | otras: b:=falso exito := falso fsi cand := calculaCandidatos(x) mientras NO exito Y quedanCandidatos(cand) i:=i+1 xsig := seleccionaCandidato(cand, x) fmientras si esPrometedor(cand, x, xsig): anotaSolucion(cand, x, xsig) fin proc anotaSolucion(cand: Candidatos; ent/sal x, xsig: Etapa) alg sol.s[xsig.k] := cand.i fin exito := btUna(xsig) si NO exito: cancelaAnotacion(cand, x, xsig) fsi fsi fmientras fsi fin proc cancelaAnotacion(cand: Candidatos; ent/sal x, xsig: Etapa) alg fin 8 Colocar Reinas en tablero – Todas (1) clase ReinasBT_TODAS N: Entero sol: Solucion clase Solucion s: array [1..N] de Entero fclase proc colocaReinas() var x: Etapa alg x.k := 0 sol.s := < crea array de ceros > btTodas(x) fin clase Etapa k: Entero fclase clase Candidatos i: Entero fclase 9 Colocar Reinas en tablero – Todas (2) func calculaCandidatos(x: Etapa) dev (cand: Candidatos) alg si x.k < N: // los candidatos son los enteros desde 1 a N proc btTodas(x: Etapa) cand.i := 0 var xsig: Etapa | otras: cand: Candidatos cand.i := N // para que no haya más candidatos alg si esSolucion(x): fsi comunicaSolucion() fsi fin proc comunicaSolucion() alg <imprime sol> fin cand := calculaCandidatos(x) mientras quedanCandidatos(cand) xsig := seleccionaCandidato(cand, x) si esPrometedor(cand, x, xsig): anotaSolucion(cand, x, xsig) btTodas(xsig) cancelaAnotacion(cand, x, xsig) fsi fmientras fin 10 Recorridos del Rey en Ajedrez – Una (1) clase ReyBT_UNA N: Entero i0, j0: Entero // posición inicial sol: Solucion mov_x, mov_y: array [1..8] de Entero proc movimientosPosibles() alg <mov_x[1],mov_y[1]> := <mov_x[2],mov_y[2]> := <mov_x[3],mov_y[3]> := <mov_x[4],mov_y[4]> := <mov_x[5],mov_y[5]> := <mov_x[6],mov_y[6]> := <mov_x[7],mov_y[7]> := <mov_x[8],mov_y[8]> := fin <-1,-1> <-1,0> <-1,1> <0,-1> <0,1> <1,-1> <1,0> <1,1> func btUna(x: Etapa) dev (exito: Logico) var xsig: Etapa cand: Candidatos alg si esSolucion(x): exito := cierto | otras: exito := falso cand := calculaCandidatos(x) mientras NO exito Y quedanCandidatos(cand) xsig := seleccionaCandidato(cand, x) si esPrometedor(cand, x, xsig): anotaSolucion(cand, x, xsig) exito := btUna(xsig) si NO exito: cancelaAnotacion(cand, x,xsig) fsi fsi fmientras fsi fin 11 Recorridos del Rey en Ajedrez – Una (2) clase Solucion s: array [1..N, 1..N] de Entero fclase clase Etapa k: Entero i, j: Entero fclase // número de casillas visitadas // casilla actual clase Candidatos c: Entero fclase func btUna(x: Etapa) dev (exito: Logico) var xsig: Etapa cand: Candidatos alg si esSolucion(x): exito := cierto | otras: exito := falso cand := calculaCandidatos(x) mientras NO exito Y quedanCandidatos(cand) xsig := seleccionaCandidato(cand, x) si esPrometedor(cand, x, xsig): anotaSolucion(cand, x, xsig) exito := btUna(xsig) si NO exito: cancelaAnotacion(cand, x, xsig) fsi fsi fmientras fsi fin 12 Recorridos del Rey en Ajedrez – Una (3) func recorridoRey() dev (exito: Logico) var x: Etapa alg <x.k, x.i, x.j> := <1, i0, j0> sol.s := < crea array de ceros > sol.s[i0, j0] := 1 exito := btUna(x) si exito: <tratar sol> fsi fin func esSolucion(x: Etapa) dev (b:Logico) alg b := (x.k = N * N) fin func btUna(x: Etapa) dev (exito: Logico) var xsig: Etapa cand: Candidatos alg si esSolucion(x): exito := cierto | otras: exito := falso cand := calculaCandidatos(x) mientras NO exito Y quedanCandidatos(cand) xsig := seleccionaCandidato(cand, x) si esPrometedor(cand, x, xsig): anotaSolucion(cand, x, xsig) exito := btUna(xsig) si NO exito: cancelaAnotacion(cand, x, xsig) fsi fsi fmientras fsi fin 13 Recorridos del Rey en Ajedrez – Una (4) func calculaCandidatos(x: Etapa) dev (cand: Candidatos) alg // los candidatos son los enteros desde 1 a 8 cand.c := 0 fin func quedanCandidatos(cand: Candidatos) dev (b: Logico) alg b := (cand.c < 8) fin func btUna(x: Etapa) dev (exito: Logico) var xsig: Etapa cand: Candidatos alg si esSolucion(x): exito := cierto | otras: exito := falso cand := calculaCandidatos(x) mientras NO exito Y quedanCandidatos(cand) xsig := seleccionaCandidato(cand, x) si esPrometedor(cand, x, xsig): anotaSolucion(cand, x, xsig) exito := btUna(xsig) si NO exito: cancelaAnotacion(cand, x, xsig) fsi fsi fmientras fsi fin func seleccionaCandidato(ent/sal cand: Candidatos; ent/sal x: Etapa) dev (xsig: Etapa) alg cand.c := cand.c + 1 xsig.k := x.k + 1 <xsig.i, xsig.j> := <x.i + mov_x[cand.c], x.j + mov_y[cand.c]> fin 14 Recorridos del Rey en Ajedrez – Una (5) func esPrometedor(cand: Candidatos; x, xsig: Etapa) dev (b: Logico) alg b := (xsig.i>=1 Y xsig.i<=N Y xsig.j>=1 Y xsig.j<=N Y func btUna(x: Etapa) dev (exito: Logico) sol.s[xsig.i, xsig.j]=0) var fin xsig: Etapa proc anotaSolucion(cand:Candidatos; ent/sal x, xsig: Etapa) alg sol.s[xsig.i, xsig.j] = xsig.k fin proc cancelaAnotacion(cand: Candidatos; ent/sal x, xsig: Etapa) alg sol.s[xsig.i, xsig.j] = 0 fin cand: Candidatos alg si esSolucion(x): exito := cierto | otras: exito := falso cand := calculaCandidatos(x) mientras NO exito Y quedanCandidatos(cand) xsig := seleccionaCandidato(cand, x) si esPrometedor(cand, x, xsig): anotaSolucion(cand, x, xsig) exito := btUna(xsig) si NO exito: cancelaAnotacion(cand, x, xsig) fsi fsi fmientras fsi fin 15 Recorridos del Rey en Ajedrez – Todas (1) clase ReyBT_TODAS N: Entero i0, j0: Entero sol: Solucion mov_x, mov_y: array [1..8] de Entero clase Solucion s: array [1..N, 1..N] de Entero fclase clase Etapa k: Entero // número de casillas visitadas i, j: Entero // casilla actual fclase clase Candidatos c: Entero fclase 16 Recorridos del Rey en Ajedrez – Todas (2) func recorridoRey() dev (éxito: Logico) alg <x.k, x.i, x.j> := <1, i0, j0> sol.s := < crea array de ceros > sol.s[i0,j0] := 1 BT_TODAS(x) fin func calculaCandidatos(x: Etapa) dev (cand: Candidatos) alg si x.k < N * N: // los candidatos son los enteros desde 1 a 8 cand.c := 0 | otras // para que no haya más candidatos cand.c := N *N fin proc comunicaSolucion() alg <imprime sol> fin proc btTodas(x: Etapa) var xsig: Etapa cand: Candidatos alg si esSolucion(x): comunicaSolucion() fsi cand := calculaCandidatos(x) mientras quedanCandidatos(cand) xsig := seleccionaCandidato(cand, x) si esPrometedor(cand, x, xsig): anotaSolucion(cand, x, xsig) btTodas(xsig) cancelaAnotacion(cand, x, xsig) fsi fmientras fin 17 La Mochila 1 – Sin Repetición (1) clase MochilaSinRepetBT // número de objetos N: Entero pesos, valores: array [1..N] de Entero pesoMax: Entero solOpt: Solucion sol: Solucion clase Solucion s: array [1..N] de Entero // valor hasta el momento valor: Entero fclase clase Etapa k: Entero // peso aún disponible capac: Entero fclase clase Candidatos i: Entero // cap: Entero fclase proc resuelveMochila() var x: Etapa alg solOpt.s := < crea array de ceros > solOpt.valor := 0 x.k := 0 x.capac := pesoMax sol.valor := 0 sol.s := < crea array de ceros > btOptimo(x) <imprime solOpt.s y solOpt.valor> fin 18 La Mochila 1 – Sin Repetición (2) func esSolucion(x: Etapa) dev (b: Logico) alg b := (x.k = N) fin func esMejor() dev (b:Logico) alg b := (sol.valor > solOpt.valor) fin proc actualizaSolucion() alg <solOpt.s, solOpt.valor> := <sol.s, sol.valor> fin proc btOptimo(x: Etapa) var xsig: Etapa cand: Candidatos alg si esSolucion(x): si esMejor(): actualizaSolucion() fsi fsi cand := calculaCandidatos(x) mientras quedanCandidatos(cand) xsig := seleccionaCandidato(cand, x) si esPrometedor(cand, x, xsig): anotaSolucion(cand, x, xsig) btOptimo(xsig) cancelaAnotacion(cand, x, xsig) fsi fmientras fin 19 La Mochila 1 – Sin Repetición (3) func calculaCandidatos(x: Etapa) dev (cand: Candidatos) alg si x.k < N: cand.i := – 1 // los candidatos son 0 ó 1 | otras: cand.i := 1 // para que no haya más candidatos fsi fin func quedanCandidatos(cand: Candidatos) dev (b:Logico) alg b := (cand.i < 1) fin proc btOptimo(x: Etapa) var xsig: Etapa cand: Candidatos alg si esSolucion(x): si esMejor(): actualizaSolucion() fsi fsi cand := calculaCandidatos(x) mientras quedanCandidatos(cand) xsig := seleccionaCandidato(cand, x) si esPrometedor(cand, x, xsig): anotaSolucion(cand, x, xsig) btOptimo(xsig) cancelaAnotacion(cand, x, xsig) fsi fmientras fin func seleccionaCandidato(ent/sal cand: Candidatos; ent/sal x: Etapa) dev (xsig: etapa) alg cand.i := cand.i + 1 xsig.k = x.k + 1 xsig.capac = x.capac - (cand.i * pesos[xsig.k]) fin 20 La Mochila 1 – Sin Repetición (4) func esPrometedor(cand: Candidatos; x, xsig: Etapa) dev (b: Logico) alg b := (xsig.capac >= 0) fin proc btOptimo(x: Etapa) proc anotaSolucion(cand:Candidatos; ent/sal x, xsig: Etapa) alg sol.s[xsig.k] := cand.i sol.valor := sol.valor + (cand.i * valores[xsig.k]) fin proc cancelaAnotacion(cand: Candidatos; ent/sal x, xsig : Etapa) alg sol.valor := sol.valor – (cand.i * valores[xsig.k]) fin var xsig: Etapa cand: Candidatos alg si esSolucion(x): si esMejor(): actualizaSolucion() fsi fsi cand := calculaCandidatos(x) mientras quedanCandidatos(cand) xsig := seleccionaCandidato(cand, x) si esPrometedor(cand, x, xsig): anotaSolucion(cand, x, xsig) btOptimo(xsig) cancelaAnotacion(cand, x, xsig) fsi fmientras fin 21