Programación lógica basada en restricciones
Transcripción
Programación lógica basada en restricciones
Programación lógica basada en restricciones Trabajo de Curso: 2008-2009 Programación lógica basada en restricciones Introducción. La programación lógica basada en restricciones [1][2] es un paradigma muy útil para formular y resolver problemas que se definen de forma natural en términos de las restricciones que deben verificar un conjunto de variables. La resolución de tales problemas consiste normalmente en encontrar la asignación de valores a las variables que permite que se verifiquen las restricciones impuestas. A esta aproximación se le denomina “satisfacción de restricciones”. En la Programación Lógica basada en Restricciones (CLP, de las siglas en inglés de Constraint Logic Programming) se incluyen recursos para poder tratar este tipo de problemas en el ámbito de un lenguaje de programación lógica como Prolog. Un problema de satisfacción de restricciones se plantea, en general, en los siguientes términos: Dados un conjunto de variables, los dominios de definición de cada variable y las restricciones que las variables deben cumplir, Encontrar una asignación de valores a las variables, de manera que no se incumpla ninguna de las restricciones impuestas. Un ejemplo [1]: En un problema de planificación de tareas (scheduling) se tienen 4 tareas, denominadas A, B, C y D. La duración de estas tareas es, respectivamente, de 2, 3, 5 y 4 horas. Las tareas no pueden ejecutarse en cualquier orden. Concretamente, la tarea A debe preceder a las tareas B y C, y B debe realizarse antes de D. El problema es encontrar los tiempos de comienzo de las tareas de manera que el tiempo de finalización (Tf) de la última tarea sea mínimo. Variables: tiempos de comienzo de cada tarea (Ta, Tb, Tc, Td) y de finalización de la última (Tf). Dominios: todas las variables son reales positivos. Restricciones: Ta + 2 ≤ Tb (la tarea A, de 2 horas de duración, debe preceder a la tarea B) Ta + 2 ≤ Tc (la tarea A precede a la tarea C) Tb + 3 ≤ Td (la tarea B precede a la tarea D) Tc + 5 ≤ Tf (la finalización de la tarea C puede marcar el final del conjunto de tareas) Td + 4 ≤ Tf (la finalización de la tarea d puede marcar el final del conjunto de tareas) La solución óptima será aquella que minimice Tf. Con estas restricciones, es posible definir el siguiente conjunto de soluciones: Ta = 0 Tb = 2 2 ≤ Tc ≤ 4 Td = 5 Tf = 9 1 Programación lógica basada en restricciones Trabajo de Curso: 2008-2009 El tiempo de comienzo queda determinado para todas las tareas excepto para la tarea C, que puede comenzar en cualquier momento en el intervalo [2,4]. Son numerosas las implementaciones de Prolog que incorporan extensiones en forma de librerías para tratar este tipo de problemas. Estas librerías se diferencian en el tipo de dominio y de restricciones que pueden tratar, de manera que los sistemas CLP se suelen agrupar en función del tipo de dominio de definición de las variables. Por ejemplo, en CLP(R) los dominios de la variables se establecen sobre números reales, y las restricciones son expresiones aritméticas definidas sobre los números reales, normalmente en forma de ecuaciones e inecuaciones lineales; de forma similar CLP(Q) se circunscribe al ámbito de los números racionales; CLP(B) a dominios booleanos y CLP(FD) a dominios finitos. Desde el punto de vista del programador el conjunto de primitivas que se incorporan en cada librería CLP(X) (por ejemplo, para expresar dominios de definición) es heterogéneo. Es relativamente frecuente encontrar implementaciones de sistemas CLP que bien difieren en la sintaxis o nombre de las primitivas, o bien no incorporan primitivas que se encuentran en otras implementaciones. SWI-Prolog dispone de sistemas CLP(R, Q y FD) en diferentes grados de desarrollo, y, aunque presentan limitaciones si los comparamos con los que es posible encontrar en sistemas más desarrollados como Eclipse-Prolog o SICStus-Prolog, servirán para cubrir los objetivos de este trabajo de curso. Se recomienda consultar la ayuda en línea de SWI-Prolog en el apartado “SWI_prolog Library” para conocer el soporte CLP incluido en la presente versión, siendo muy recomendable emplear siempre la última versión “estable” disponible. Objetivos y estrategia de desarrollo del trabajo. El objetivo de este trabajo de curso es resolver un conjunto de problemas CSP, de dificultad progresiva. La siguiente colección de problemas simples son ejemplos de problemas que se pueden resolver con facilidad con este tipo de técnicas. Lo alumnos deberán resolver como mínimo esta colección de problemas simples y el problema de las fichas de dominó. Es posible, previa consulta con el profesor responsable, el reemplazo de algunos de estos problemas por otros de dificultad similar. En todos los problemas se pide: Obtener una representación adecuada del problema en términos de definición de dominios y de restricciones. Implementar un programa Prolog que resuelva el problema. La solución del problema. Problemas simples. 1. El problema de las N-Reinas. Se pide resolver el clásico problema de cómo disponer un N reinas sobre un tablero de ajedrez de NxN sin que ninguna de ellas pueda ser atacada otra reina. 2 Programación lógica basada en restricciones Trabajo de Curso: 2008-2009 2. Sudoku. Se trata de un juego cuyo objetivo es completar una cuadrícula de 9x9, que a su vez está dividida en nueve áreas o “cajas” de 3x3, con los dígitos del 1 al 9, obedeciendo las siguientes restricciones: En cada columna no puede haber dígitos repetidos. En cada fila no puede haber dígitos repetidos. En cada caja no puede haber dígitos repetidos. 3. Máximo beneficio. Supóngase una empresa que fabrica tres tipos de productos. Cada producto genera un beneficio a la empresa pero también le supone un coste (por ejemplo de espacio). El primer producto se vende en 3 unidades de dinero y requiere de 2 unidades de espacio. El segundo ítem se vende por 4 unidades y requiere 3 unidades de espacio. Y el tercer producto se vende por 10 unidades de dinero, pero demanda 7 unidades de espacio. Diseñar un programa que permita descubrir una solución que maximice el beneficio neto cuando el espacio es limitado. 4. Comprando zapatos. Harriet, tras volver de un centro comercial, describe a su amiga Aurora los zapatos que ha comprador. A Aurora le han encantado los cuatro tipos de zapatos que Harriet ha comprado (esclavas, botas, zapatos de tacón y sandalias), el problema es que Harriet no recuerda las zapatarías en las que compró cada uno de los modelos. Sabe que compró en The Foot Farm, Heels , The Shoe Palace y en Tootsies. ¿Podrías ayudarlas a recordar dónde y en qué orden Harriet compró cada modelo? Harriet sí que recuerda lo siguiente: Harriet compró las esclavas en Heels. La zapatería que visitó justo después de comprar las botas no era Tootsies. The Foot Farm fue la segunda tienda donde compró. Tras salir de The Shoe Palace, Harriet visitó dos tiendas más antes de comprar las sandalias. 5. Crucigrama de sumas. Dado un cuadrado como el de la izquierda en la siguiente figura, rellenar las casillas en blanco con números enteros en el intervalo [1,9] de manera que al sumar el contenido por filas y por columnas se obtenga en el resultado indicado por el número inscrito en el triángulo. Los números de una fila o columna deben ser todos diferentes. Un solución se muestra en la tabla de la derecha. 11 21 8 11 21 8 24 24 8 9 7 10 10 2 7 1 6 6 1 5 Un problema más complejo. 6. Las fichas de Dominó. Un tablero rectangular contiene un cierto número de piezas de Dominó dispuestas de manera que cubren todas las casillas del tablero. En cada casilla del tablero aparece el número de puntos de una de las mitades de una ficha. El 3 Programación lógica basada en restricciones Trabajo de Curso: 2008-2009 problema consiste en decidir cómo deben asociarse dos casillas contiguas para definir el perímetro de todas las fichas involucradas. Normalmente la dificultad del problema depende del número más alto de ficha (d) que contiene el tablero. Para d = 3, un ejemplo de problema y su única solución se muestran en la siguiente figura. Sobre la representación en el problema del dominó. Parece ser la representación del problema la principal dificultad a la hora de intentar resolverlo. Hay varias representaciones posibles, y es probable que alguno de Uds idee otra mejor que la que vamos a comentar aquí. Por tanto, en absoluto debe entenderse como “obligatorio” el uso de esta representación. La idea consiste en describir la estructura del tablero en base a dos variables por cada celda (i,j) del tablero, donde i ( 1≤ i ≤ nº filas) representa la fila y j ( 1≤ j ≤ nº columnas) la columna. Las variables son las siguientes: Eij tomará el valor 1 si y sólo si el borde “Este” (el borde derecho) de la celda (i,j) representa la línea media de una ficha del dominó. En el tablero del ejemplo, E11 = 0, pero E12=1. En otro caso, Eij=0. De forma similar, la variable Sij tomará el valor 1 si y sólo si el borde “Sur” (el borde inferior) de la celda (i,j) representa la línea media de una ficha del dominó. Así, en el tablero del ejemplo, S11 = 1, pero S12=1. En otro caso, Sij=0. En base a esta idea es fácil representar las restricciones de conectividad de las celdas, es decir, las formas en las que se puede cubrir una celda del tablero con una ficha del dominó. Veamos algunos casos: Celda (1,1): E11+S11 = 1. Esta restricción recoge la idea de que en la esquina del tablero sólo es posible ubicar una ficha en dos posiciones diferentes. Celda (1,3): E12 + S13 + E13= 1. En el ejemplo, E12=1 y S13=E13=0. Celda (2,2): E21 + S12 + E22 + S22= 1. Con la disposición de la figura, sólo E22=1. Celda (4,1): S31 + E41 = 1. En nuestro ejemplo, S31=0 y E41=1. 4 Programación lógica basada en restricciones Trabajo de Curso: 2008-2009 Celda (4,5): S35 + E44 = 1. Este tipo de restricciones dará lugar a tantas restricciones como celdas tenga el tablero. Nótese que estas restricciones sólo dependen de las dimensiones del tablero. Planteando estas restricciones no hemos recogido todas las condiciones de que definen un problema particular. Concretamente, el otro conjunto de restricciones deberá establecer las posibles ubicaciones en el tablero para cada ficha del dominó. En nuestro caso, las fichas que hay que colocar sobre el tablero son las diez siguientes: <0,0>, <0,1>, <0,2>, <0,3>, <1,1>, <1,2>, <1,3>, <2,2>, <2,3>, <3,3> Si prestamos atención a los números que ocupan las celdas del tablero, vemos que algunas fichas, como <1,1> o <2,2> sólo pueden ocupar una posición. De hecho, este análisis debería traducirse en el establecimiento de dos nuevas restricciones: S14=1 y E41=1. Para otras fichas, por ejemplo <0,2>, existen más posibilidades, pero que también se pueden recoger en una restricción similar a las anteriores: E22+S34+E44=1. A partir de aquí les toca a Uds. Espero que estas notas hayan servido para arrojar un poco de luz sobre este ejercicio. Sobre la realización práctica. Es conveniente que la depuración del código se realice inicialmente sobre problemas más sencillos que el propuesto en el guión del trabajo, que – por otra parte - tampoco tiene que ser el único que se intente resolver. Los dos problemas siguientes pueden ser interesantes en la fase de desarrollo, donde el primer argumento define el problema y el segundo (d) de domino/2 indica la dimensión del problema, es decir, la puntuación de cada mitad de una ficha del dominó estará comprendida en el intervalo cerrado [0,d]. A. domino([ [0,0,1], [0,1,1] ], 1). B. domino([ [0,0,1,1], [0,1,1,2], [0,2,2,2] ], 2). Es fácil comprobar que el problema A tiene 3 posibles soluciones y el B siete. 5 Programación lógica basada en restricciones Trabajo de Curso: 2008-2009 Sobre la forma de presentar los resultados. Realmente hay muchas formas de presentar los resultados, pero la siguiente es sencilla, pero es muy clara y se puede construir fácilmente para un terminal alfanumérico. 1 3-0 1 2 | | | 3 2-0 1 3 3-3 0-0 1 | 2-2 1-2 0 Sobre la memoria del trabajo. Tras finalizar el desarrollo del trabajo, y dentro del plazo que se establezca al efecto, los alumnos deberán entregar una memoria del trabajo realizado. Esta memoria deberá reflejar, en un estilo técnico y correcto, el trabajo realizado en cada una de sus fases, los resultados obtenidos y unas instrucciones que indiquen la forma de compilar la aplicación y ejecutarla. Más concretamente, la memoria de la práctica deberá incluir los siguientes puntos: Definición del problema. En este primer punto se debe realizar una clara definición del problema que se va a resolver, incluyendo - si fuera el caso - qué restricciones se han impuesto y su justificación. Descripción de la solución adoptada. En este apartado se indicará básicamente la estructuración de la solución propuesta y cómo se ha trasladado este enfoque a la implementación. Es importante destacar explícitamente los objetivos específicos que este desarrollo pretende alcanzar. Este aspecto es clave a la hora de establecer, en el apartado de conclusiones, la valoración final del trabajo realizado. Implementación. Aquí se debe explicar la implementación realizada. Debe incluirse una descripción funcional de los distintos módulos que componen la aplicación, haciendo hincapié en algún elemento - que a juicio del alumno – sea un elemento determinante en cuanto a capacidad del sistema, velocidad de ejecución, facilidad de uso, etc. Experimentos. Es importante demostrar la corrección y capacidades del sistema demostrando su aplicación sobre un conjunto de problemas lo más completo posible. Si se emplean ficheros de datos debe indicarse con claridad su ubicación y nombre completo. Conclusiones. En este apartado se deberá realizar una valoración crítica de los resultados obtenidos, destacando tanto aquellos aspectos positivos o a destacar como las limitaciones o deficiencias que se hayan detectado. Se valorará la riqueza y rigor de las conclusiones a tenor de los resultados incluidos en el apartado de los experimentos y de los 6 Programación lógica basada en restricciones Trabajo de Curso: 2008-2009 objetivos consignados en el segundo apartado de la memoria (Descripción de la solución adoptada). Apéndice. Además de lo anterior se incluirá a modo de apéndice un pequeño manual que detalle la lista de ficheros que componen la aplicación, su organización en directorios (si la hubiera) y las instrucciones necesarias para compilar y ejecutar el programa. Normas de entrega. La memoria del trabajo de curso y el código deberán ser remitidos por correo electrónico al profesor responsable de la asignatura ([email protected]) dentro del periodo que se establezca al efecto. Posteriormente se concertará una fecha para la defensa del trabajo entre el profesor responsable y el alumno. Bibliografía. *1+ I. Bratko, “Prolog Programming for Artificial Intelligence”, Addison-Wesley, 3ª edición, 2001. [2] Constraint Logic Programming (CLP), http://en.wikipedia.org/wiki/Constraint_logic_programming 7