Está en la página 1de 26

INTRODUCCION AL LENGUAJE PROLOG

Indice
1. Introduccin o 2. Caracter sticas Generales 2.1. Evolucin histrica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o o 2.2. Esquema general de trabajo en Prolog . . . . . . . . . . . . . . . . . . . . . . . . 2.3. Implementaciones de Prolog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.1. SICStus Prolog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.2. SWI-Prolog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3. Prolog y el paradigma de la Programacin Lgica o o 3.1. Sintaxis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1. Trminos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e 3.1.2. Programas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 2 3 4 5 6 6 6 6 8

3.1.3. Consultas para la activacin de programas . . . . . . . . . . . . . . . . . . 10 o 3.1.4. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.2. Semntica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 a 4. Predicados Predenidos 15

4.1. Aritmtica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 e 4.1.1. Operadores aritmticos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 e 4.1.2. Predicados aritmticos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 e 4.1.3. Programas aritmticos en Prolog . . . . . . . . . . . . . . . . . . . . . . . 17 e 4.2. Entrada/Salida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 4.3. Control: el corte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 4.3.1. Denicin y propiedades . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 o 4.3.2. Usos del corte. Ejemplos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

1.

Introduccin o

En este documento se realiza una breve introduccin al lenguaje de programacin Prolog, con o o el objetivo fundamental de mostrar cmo se da el paso desde el concepto de programacin o o lgica pura estudiado en el tema anterior a un lenguaje de programacin real. En efecto, o o el lenguaje Prolog se puede ver como una extensin de la programacin lgica pura, en el o o o sentido de que, adems de permitir programar de acuerdo con el paradigma de la programacin a o lgica, incorpora una serie de elementos adicionales cuyo objetivo es ofrecer una herramienta o de programacin que sea util en la prctica. o a Despus de una descripcin de las caracter e o sticas generales del lenguaje (evolucin histrica, o o esquema general de trabajo e implementaciones existentes), el apartado 3 estudia el funcionamiento de Prolog desde el punto de vista de la programacin lgica pura, basado en la Prograo o macin Lgica Denida estudiada en el tema anterior. Su extensin, que se realiza mediante la o o o introduccin de los denominados predicados predenidos, se resume en el apartado 4. o No se abordan, por lo tanto, ms que algunos de los aspectos ms relevantes del lenguaje. a a Para un estudio ms en profundidad de Prolog se recomienda consultar los siguientes libros (los a tres primeros son libros de carcter introductorio, mientras que el ultimo trata aspectos ms a a avanzados). L. Sterling and E. Shapiro. The Art of Prolog. The MIT Press, Cambridge, Mass., second edition, 1994. W.F. Clocksin and C.S. Mellish. Programming in Prolog. Springer-Verlag, Berlin, fourth edition, 1994. I. Bratko. Prolog Programming for Articial Intelligence. Addison-Wesley, Reading, Massachusetts, third edition, 2001. R. OKeefe. The Craft of Prolog. The MIT Press, Cambridge, MA, 1990.

2.
2.1.

Caracter sticas Generales


Evolucin histrica o o

Prolog (del francs, PROgrammation en LOGique) fue el primer lenguaje de programacin bae o sado en el paradigma de la programacin lgica. Se implement por primera vez a principios de o o o los aos setenta en la Universidad de Marsella (Francia), por un equipo dirigido por A. Colmen raeur, utilizando resultados tericos aportados por R. Kowalski (Universidad de Edimburgo). o Aunque con ciertas dicultades iniciales, debido principalmente a la novedad del paradigma y a la escasa eciencia de las implementaciones disponibles, el lenguaje se fue expandiendo rpidamente, sobre todo en Europa y en Japn (en este ultimo pa la programacin lgica a o s o o se incluy como parte central del proyecto de ordenadores de quinta generacin de los aos o o n ochenta). En 1995 el lenguaje se normaliza con el correspondiente estndar ISO. En la actuaa lidad Prolog se ha convertido en una herramienta de desarrollo de software prctica y de gran a aceptacin para la que se dispone de mltiples compiladores, tanto comerciales como de libre o u distribucin. o 2

2.2.

Esquema general de trabajo en Prolog

El esquema general de trabajo en Prolog es el siguiente: 1. Escribir un programa lgico en Prolog. o Como se ha visto en el tema anterior, un programa lgico es un conjunto nito de frmulas o o lgicas, que reejan el conocimiento del que se dispone acerca del problema a resolver. o Por lo tanto, un programa en Prolog estar formado por una serie de frmulas lgicas a o o que, evidentemente, tendrn que adaptarse a la sintaxis espec a ca del lenguaje (sta se e detalla ms adelante). Podrn asimismo incluirse comentarios: a a % El smbolo % precede los comentarios en una nica lnea u /* Los comentarios en varias lneas empiezan con /* y terminan con */ */ Los programas se pueden escribir mediante cualquier editor de textos, aunque, como se ver despus, existen editores especiales que facilitan la escritura de programas en Prolog. a e Una vez escrito un programa, ste se deber guardar en un chero (la extensin habitual e a o para los programas en Prolog es .pl). 2. Iniciar el sistema Prolog y cargar un programa. Cuando se inicia un sistema Prolog, ste muestra por pantalla una l e nea con el siguiente formato: ?que indica que el sistema est esperando la introduccin por parte del usuario de alguna a o consulta. Para poder trabajar con un programa escrito previamente, es necesario cargar el chero correspondiente en el sistema Prolog. Lo anterior se puede hacer de dos formas distintas: - interpretando el programa por medio del intrprete del lenguaje. Esta solucin es la e o ms habitual cuando se est probando un programa, y la accin se conoce como a a o consultar un chero. Para realizarla, basta con utilizar el predicado del sistema consult, con el nombre del chero que se quiere cargar: ?- consult(c:/Prolog/prueba.pl). Lo anterior es equivalente a escribir simplemente el nombre del chero entre corchetes: ?- [c:/Prolog/prueba.pl]. - compilando el programa por medio del compilador del lenguaje. El cdigo compilado o es ms rpido que el cdigo interpretado, aunque ofrece menos facilidades en lo que a a o a depuracin se reere. La compilacin de un programa se realiza por medio del o o predicado del sistema compile: ?- compile(c:/Prolog/prueba.pl). 3

En cualquiera de los dos casos, la respuesta del sistema puede ser de dos tipos: - si se ha detectado algn error sintctico en el programa, el sistema Prolog avisa de ello u a mediante un mensaje. En estos casos habr que volver a editar el programa para a corregir los errores que contiene y volver a cargarlo. - en caso contrario, el sistema responde con la palabra yes, que indica que el programa se ha cargado correctamente y el sistema est listo para recibir consultas del usuario. a Nota: la mayor de los sistemas Prolog ofrecen un entorno de programacin interactivo a o dotado de mens mediante los cuales se ofrecen las acciones ms habituales, entre ellas la u a carga de cheros tanto para ser interpretados como para ser compilados (normalmente, File/Consult... y File/Compile...). 3. Activar un programa desde el sistema Prolog. Una vez que se ha cargado correctamente un programa, el sistema est preparado para a recibir las consultas del usuario relativas al problema que se pretende resolver. Para ello bastar con escribir dichas consultas, siguiendo la sintaxis espec a ca del lenguaje, en la l nea de consultas del sistema. El formato de estas consultas as como las posibles reacciones del sistema ante ellas se detallan ms adelante. a o Nota: Los sistemas Prolog suelen incorporar un mecanismo de depuracin que permite seguir paso a paso la ejecucin de las consultas, establecer puntos de corte en la ejecucin, o o etc. Su funcionamiento bsico es el siguiente: a para entrar en modo de depuracin debe escribirse el predicado del sistema trace o en la l nea de consultas: ?- trace. A partir de ese momento, las consultas que se realicen se ejecutarn en modo de a depuracin, mostrando una despus de otra todas las llamadas realizadas internao e mente por el sistema Prolog. Para avanzar en la depuracin, basta con pulsar la tecla o RETURN. Tambin puede pulsarse la tecla h para obtener ayuda sobre las distine tas opciones disponibles. En particular, la tecla n permite abandonar el proceso de depuracin. o para desactivar el modo de depuracin se utiliza el predicado notrace: o ?- notrace. Para una informacin ms detallada sobre el mecanismo de depuracin de Prolog se o a o recomienda leer el cap tulo 8 del libro de Clocksin y Mellish citado en la introduccin o o consultar el manual de referencia del sistema Prolog que se est utilizando. e 4. Salir del sistema Prolog. Para salir del sistema Prolog basta con escribir el predicado del sistema halt en la l nea de comandos: ?- halt.

2.3.

Implementaciones de Prolog

Como se ha comentado previamente, existen muchas implementaciones del lenguaje Prolog, tanto comerciales como de libre distribucin. La mayor de ellas se adaptan al estndar ISO, o a a 4

por lo que los programas Prolog que se generen de acuerdo con dicho estndar podrn ejecutarse a a en cualquiera de estos sistemas. En esta asignatura (y en este documento) se va a utilizar la implementacin comercial deo nominada SICStus Prolog, para la cual la URJC dispone de una licencia de Campus. A continuacin se describe brevemente tanto este sistema como otro sistema Prolog, de dominio o pblico, denominado SWI-Prolog. u 2.3.1. SICStus Prolog

SICStus Prolog es un compilador de Prolog comercial, desarrollado por el Instituto Sueco de Ciencias de la Computacin (SICS), compatible con el estndar ISO-Prolog, con facilidades de o a depuracin, interfaz con el lenguaje C, estructuracin modular, bibliotecas con las estructuras o o de datos ms habituales, etc. a Aunque SICStus Prolog se puede usar directamente (activando el ejecutable correspondiente y siguiendo el esquema general de trabajo en Prolog descrito ms arriba), lo ms recomendable a a es usarlo a travs del editor de textos GNU Emacs (Emacs es un potente editor de textos, e programable y de libre distribucin, que puede obtenerse en la URL http://www.emacs.org). o Para ello, SICStus Prolog incluye en su distribucin un chero de interfaz con Emacs (.emacs), o que aporta un modo de edicin especial para programas en Prolog, as como acceso directo o desde el editor Emacs a la carga de programas, al sistema SICStus Prolog y a su manual de ayuda. As una vez instalado dicho interfaz, el modo de trabajar en SICStus Prolog a travs del editor , e Emacs ser el siguiente: a 1. Iniciar Emacs. El editor Emacs se inicia mediante el ejecutable runemacs.exe, ubicado en el subdirectorio bin del directorio en el que se haya instalado el editor. 2. Crear/editar un programa Prolog. Tanto para crear un nuevo programa como para modicar un programa ya existente se usar la opcin del men de Emacs File/Open File..., o, alternativamente, la a o u combinacin de teclas CONTROL-X CONTROL-F. Si el nombre facilitado se corresponde o con un chero existente, el editor mostrar su contenido en pantalla; en caso contrario, a mostrar una ventana vac en la que se podr escribir el nuevo programa. Las entradas de a a a los mens Edit y File (o las combinaciones de teclas asociadas) ofrecen las opciones u habituales para editar y guardar (CONTROL-X CONTROL-S) el contenido del chero. 3. Cargar un programa e iniciar el sistema Prolog. Si el chero abierto en el punto anterior tiene extensin .pl, el interfaz de SICStus o Prolog con Emacs aadir automticamente a la barra de mens de Emacs una nueva n a a u entrada bajo el nombre Prolog que incluye, entre otras, las opciones pertinentes para consultar (CONTROL-C CONTROL-F) o compilar el programa correspondiente. Al elegir cualquiera de ellas, no slo se cargar el programa en el sistema sino que adems o a a se abrir una nueva ventana con el sistema SICStus Prolog, que permitir realizar las a a consultas pertinentes. 5

Tambin es posible acceder desde Emacs al sistema de ayuda de SICStus Prolog: e - el men Help/Manuals/Browse Manuals with Info permite acceder a los manuales de u usuario de SICStus. - la opcin Help on Predicate (CONTROL-C ?) del men contextual Prolog antes o u citado ofrece ayuda sobre los predicados predenidos de Prolog. 2.3.2. SWI-Prolog

SWI-Prolog es un compilador de Prolog de dominio pblico diseado e implementado en la Uniu n versidad de Amsterdam, compatible con el estndar ISO y disponible para distintas platafora mas. Se puede obtener en la direccin http://www.swi-prolog.org. La versin para Windows o o consta de un unico chero ejecutable que instala automticamente el sistema. Este se utiliza de a acuerdo con el esquema general de trabajo en Prolog descrito ms arriba. a

3.

Prolog y el paradigma de la Programacin Lgica o o

Como se ha visto previamente, existen muchos modelos distintos de programacin lgica, que o o se distinguen dependiendo del tipo de Lgica utilizada para representar el conocimiento y del o mecanismo de demostracin automtica elegido. El lenguaje Prolog se basa en la Programacin o a o Lgica Denida estudiada en el tema anterior, pero con ciertas peculiaridades, tanto sintcticas o a como semnticas, que se discuten a continuacin. a o

3.1.
3.1.1.

Sintaxis
Trminos e

Al igual que en Lgica de Primer Orden, los trminos en Prolog se clasican en tres categor o e as: constantes, variables y trminos compuestos. e Constantes Prolog distingue dos tipos de constantes: Nmeros. Este tipo de constantes se utilizan para representar tanto nmeros enteros como u u nmeros reales y poder realizar con ellos operaciones aritmticas. u e - La representacin ms corriente de los nmeros enteros es la notacin decimal habitual o a u o (por ejemplo 0, 1, -320, 539, etc) aunque tambin se pueden representar en otras e bases no decimales. - Los nmeros reales se pueden representar tanto en notacin decimal (por ejemplo u o 1.0, -3.14) como en notacin exponencial (por ejemplo 4.5E6, -0.12e+3, 12.0e-2). En o ambos casos deber haber siempre por lo menos un d a gito a cada lado del punto.

Atomos. Los tomos (no confundir con las frmulas atmicas de la LPO) se utilizan para a o o dar nombre a objetos espec cos, es decir, representan individuos concretos. Existen tres clases principales de tomos: a - cadenas formadas por letras, d gitos y el s mbolo de subrayado, que deben empezar necesariamente por una letra minscula. u Cadenas vlidas: f, pepe1, libro33a, libro_blanco. a Cadenas no vlidas: 1libro, libro-blanco, _hola, Libro. a - cualquier cadena de caracteres encerrada entre comillas simples. Ejemplos: SICStus Prolog, Libro-blanco, 28003 Madrid. Estos tomos son utiles cuando se necesita trabajar con constantes que empiecen por a una letra mayscula o por un d u gito. - existe adems otro tipo de tomos, compuestos por combinaciones especiales de signos, a a de uso menos comn. u Variables Las variables en Prolog se representan mediante cadenas formadas por letras, d gitos y el s mbolo de subrayado, pero deben necesariamente empezar por una letra mayscula o por un s u mbolo de subrayado. Ejemplos: X, Resultado_1, Entrada, _total3, _3bis, _ Las variables que empiezan con un s mbolo de subrayado, _, se denominan variables annimas, o y se usan cuando se necesita trabajar con variables cuyos posibles valores no interesan. Su utilidad se describir ms adelante al analizar la construccin de programas y consultas. a a o Trminos Compuestos e Los trminos compuestos, o estructuras, se construyen mediante un s e mbolo de funcin, denoo minado functor, que se denota mediante un tomo, seguido, entre parntesis, por una serie de a e trminos separados por comas, denominados argumentos. e Ejemplos: fecha(1,mayo,2001), punto(X,Y), recta(punto(1,2), punto(3,5)) Nota: al escribir un trmino compuesto, no puede haber ningn espacio entre el functor y e u el parntesis abierto previo a los argumentos. Por ejemplo, punto (X,Y) no es un trmino e e compuesto correcto y producir un error de compilacin. a o Prolog tambin permite escribir ciertos trminos compuestos en forma de operadores, generale e mente en notacin inja en el caso de functores de aridad 2 y en notacin preja o postja en o o el caso de functores de aridad 1. Este es el caso de los operadores aritmticos predenidos de e Prolog, que se mencionarn ms adelante, y que permiten escribir trminos compuestos de la a a e forma X+Y o -X en lugar de +(X,Y) o -(X). El programador tambin puede denir sus propios e operadores. Uno de los trminos compuestos ms importantes y utiles que ofrece Prolog son las listas, e a secuencias ordenadas de cero o ms elementos, donde los elementos pueden ser cualquier tipo a de trmino. Prolog representa las listas teniendo en cuenta su estructura recursiva: e - la lista vac se representa mediante el tomo []. a a 7

- toda lista no vac tiene una cabeza (que ser cualquier trmino) y un resto (que ser una a a e a lista), y se representa mediante un trmino compuesto de aridad 2, cuyo functor es un e punto y cuyos argumentos son, respectivamente, la cabeza y el resto de la lista. Ejemplos: la lista compuesta por un unico elemento, la constante a, se representa como (a, []). La lista compuesta por los elementos a, b y c se corresponde con la estructura (a, (b, (c, []))). Dado que la notacin anterior puede resultar incmoda a la hora de escribir listas complicadas, o o Prolog admite tambin una notacin ms sencilla que consiste en enumerar entre corchetes e o a todos los elementos de la lista, separados por comas. Con esta notacin, las dos listas del o ejemplo anterior se representar an, respectivamente, como [a] y [a, b, c]. Prolog tambin dispone e de otra notacin para las listas, que consiste en representar la lista con cabeza X y resto Y o mediante el trmino [X|Y ]. Esta ultima notacin es fundamental para poder separar la cabeza e o del resto de una lista. Su utilidad en la prctica se ver en las clases de problemas. a a 3.1.2. Programas

Los programas Prolog son programas lgicos denidos, y estn por lo tanto compuestos por o a una serie de clusulas de Horn positivas, esto es, hechos y reglas. Hay que tener en cuenta sin a embargo las siguientes diferencias en cuanto a la notacin empleada en la Programacin Lgica o o o Denida: Los s mbolos de predicado se denotan mediante atomos, por lo que no pueden empezar, como ocurre en Programacin Lgica, mediante una letra mayscula. Obsrvese por lo o o u e tanto que el lenguaje Prolog no distingue entre s mbolos de predicado, s mbolos de funcin y constantes, puesto que todos ellos se representan mediante tomos (el compilador o a distingue unos de otros dependiendo del contexto en el que aparecen). Para referirse a un predicado nombre_predicado se suele emplear la notacin nombre_predicado/n, donde o n indica el nmero de argumentos del predicado. u Los hechos deben terminar con un punto y omitir el s mbolo utilizado en Programacin Lgica. As el hecho A se escribe en Prolog de la forma A.. o o , Las reglas deben tambin terminar con un punto y sustituir el s e mbolo de la Programacin Lgica por el s o o mbolo :-. As la regla A A1 , . . . , An se escribe en Prolog , de la forma A :- A1 , . . . , An .. a Nota: Al trabajar en Prolog se suele aplicar un convenio estndar para describir el uso de los predicados (tanto predenidos como denidos por el programador): en los programas, las clusulas de cada predicado debern ir precedidas de un comentario incluyendo una l a a nea que describa su uso, as como una descripcin en lenguaje natural de su cometido. El convenio para o describir el uso de un predicado es el siguiente: nombre_predicado(#NomVar_1, ...., #NomVar_n) donde NomVar_1, ..., NomVar_n son nombres de variables y el s mbolo #, que sirve para indicar cmo debe usarse el argumento correspondiente al realizarse una consulta, puede tomar uno de o los tres siguientes valores: 8

+ para indicar que el argumento correspondiente debe estar, en la consulta, instanciado con un trmino no variable (este tipo de argumentos se corresponden por lo tanto con parmetros e a de entrada). - para indicar que el argumento correspondiente no debe estar instanciado en la consulta, es decir, debe ser una variable (este tipo de argumentos se corresponden por lo tanto con parmetros de salida). a ? para indicar que el argumento puede estar tanto instanciado como no instanciado (es decir, se trata de parmetros que se pueden usar tanto para entrada como para salida). a Por ejemplo, el predicado predenido sort/2, que sirve para ordenar listas de elementos, se describe como sort(+Lista1, ?Lista2), indicando as que para utilizarlo el primer argumento de be estar instanciado (debe ser una lista concreta). Por lo tanto, el predicado sort/2 se podr utia lizar en consultas de la forma ?- sort([c,v,a], X). o ?- sort([c,v,a], [a,c,v])., pero si se intenta hacer una consulta en la que el primer argumento no est instanciado, como e por ejemplo ?- sort(X, [c,v,a])., se producir un error. a Ejemplo: Los programas lgicos para el clculo del factorial y la suma de nmeros naturales o a u estudiados en el tema anterior eran programas lgicos denidos, por lo que se pueden convertir o fcilmente en programas Prolog con slo adaptar su sintaxis de acuerdo con lo establecido ms a o a arriba (cheros factorial.pl y suma.pl):
PROGRAMA LOGICO DEFINIDO Factorial(0,s(0)) Factorial(s(x),s(x)*y) Factorial(x,y) PROGRAMA PROLOG % factorial(?X,?Y) % cierto si Y es el factorial de X factorial(0,s(0)). factorial(s(X),s(X)*Y) :- factorial(X,Y). % suma(?X,?Y,?Z) % cierto si Z es la suma de X e Y suma(X,0,X). suma(X,s(Y),s(Z)) :- suma(X,Y,Z).

Suma(x,0,x) Suma(x,s(y),s(z)) Suma(x,y,z).

Obsrvese que en los ejemplos anteriores las variables X, Y y Z aparecen a ambos lados de las e respectivas reglas. Existen sin embargo casos en los que una variable aparece slo a un lado de o una regla y sus posibles valores no tienen importancia. En estos casos no es necesario pensar un nombre de variable sino que basta con usar la variable annima _. o Ejemplo: Supngase que, dado el predicado factorial, se necesita denir a partir de l un o e predicado es_factorial(X) que es cierto si X es el factorial de algn nmero natural. Una u u forma de denir este predicado ser estableciendo que X es un factorial siempre y cuando a exista algn Y tal que X sea el factorial de ese Y , es decir: u % es_factorial(?X): cierto si X es el factorial de algn nmero u u es_factorial(X) :- factorial(Y,X). Sin embargo, en este caso el posible valor de la variable Y es indiferente, puesto que lo unico que se quiere saber es si X es el factorial de algn nmero, sin importar quien sea ste. As la u u e , denicin anterior se podr sustituir por: o a es_factorial(X) :- factorial(_,X). 9

3.1.3.

Consultas para la activacin de programas o

Al estar Prolog basado en la Programacin Lgica Denida, las unicas consultas que se pueden o o realizar para activar un programa Prolog se corresponden con clusulas de Horn negativas, a esto es, clusulas objetivo (clusulas meta). Se recuerda que estas clusulas, que son de la a a a forma A1 , . . . , An , se corresponden con la negacin de frmulas x1 . . . xp (A1 . . . An ), o o p 0, n 1, donde A1 , . . . , An son predicados. En Prolog, las consultas deben terminar siempre con un punto, y el s mbolo de la Programacin Lgica debe sustituirse por el s o o mbolo ?-. As la consulta A1 , . . . , An se escribe en Prolog de la forma ?- A1 , . . . , An .. Obsrvese , e sin embargo que no ser necesario escribir el s a mbolo ?-, puesto que, como se ha comentado antes, dicho s mbolo aparece directamente en el sistema Prolog. Ejemplo: Dados los programas para el clculo del factorial y para la suma facilitados previaa mente, algunas consultas posibles ser las siguientes: an ?- factorial(s(s(s(0))), Fact3). Cunto vale el factorial de 3? a ?- factorial(s(s(0)), s(s(0))). Es cierto que el factorial de 2 es 2? ?- factorial(0,Z), factorial(s(s(0)),Z). Existe algn nmero natural que sea igual u u al factorial de 0 y al factorial de 2? Cul? a ?- suma(s(0), s(0), X). Cunto vale la suma 1+1? a ?- suma(X, Y, s(s(0))). Qu nmeros existen tales que su suma sea 2? e u ?- suma(s(0), Y, s(s(s(0)))). Cules son los nmeros tales que sumados a 1 dan 3? a u Las consultas anteriores incluyen variables no annimas, puesto que el objetivo no es slo saber o o si existen nmeros que cumplan lo pedido sino que se desea adems conocer su valor. Existen u a sin embargo ocasiones en las que las consultas pueden incluir variables annimas. o Ejemplo: En la ultima consulta del ejemplo anterior se pretend averiguar cul es el nmero a a u natural tal que sumado a 1 da 3. Sin embargo, si lo unico que se desea saber es si existe algn u nmero natural tal que sumado a 1 d 3, bastar con utilizar una variable annima: u e a o ?- suma(s(0), _, s(s(s(0)))). 3.1.4. Resumen

Como se acaba de ver, la sintaxis del lenguaje Prolog, aunque se basa en la sintaxis de la Programacin Lgica Denida, presenta ciertas diferencias respecto a esta ultima. A continuacin o o o se resumen las ms importantes: a - los s mbolos de variable se escriben empezando por una letra mayscula o por un s u mbolo de subrayado. - los s mbolos de predicado se escriben empezando por una letra minscula, al igual que los u s mbolos de funcin y las constantes. o

10

- las clusulas de Horn terminan siempre con un punto. Adems: a a en las reglas, el s mbolo se sustituye por el s mbolo :- en los hechos, el s mbolo desaparece. en las clusulas objetivo, el s a mbolo se sustituye por el s mbolo ?-. La siguiente tabla resume las distintas notaciones para clusulas de Horn vistas hasta el moa mento: NOTACION clausular lgica estndar o a prog. lgica o Prolog REGLAS {A1 , . . . , An , A} x1 . . . xp [(A1 . . . An ) A] A A 1 , . . . , An A :- A1 , . . . , An . HECHOS {A} x1 . . . xp (A) A A. METAS {A1 , . . . , An } x1 . . . xp (A1 . . . An ) A 1 , . . . , An ?- A1 , . . . , An .

3.2.

Semntica a

El mecanismo de demostracin automtica utilizado por Prolog es el sistema de Resolucin o a o SLD estudiado en el tema anterior, pero implementado de acuerdo con las siguientes pautas: Unicacin. Prolog usa el algoritmo de unicacin estndar estudiado en el tema anterior o o a pero, por razones de eciencia, no suele incluir el test de ocurrencia. Aunque la omisin de o este test puede llevar a la obtencin de resultados errneos, esto ocurre raramente. Prolog o o permite al programador la utilizacin directa de su algoritmo de unicacin mediante los o o dos siguientes predicados predenidos, que se pueden usar en notacin inja: o - el predicado =, que devuelve cierto si las dos expresiones que se le pasan resultan ser, omitiendo el test de ocurrencia, unicables. - el predicado \=, que devuelve cierto si el predicado = falla y falso en caso contrario. Ejemplos: ?- f(X, g(b,c)) = f(Z, g(Y,c)). Y = b, Z = X ? yes ?- f(X, g(b,c)) = f(Z, g(Y,d)). no ?- [a,b,[c,d]] = [X|Y]. X = a, Y = [b,[c,d]] ? yes ?- 3+5 = 8. no % 3+5 no es ms que el trmino compuesto +(3,5) a e 11

?- X = f(X). X = f(f(f(f(f(f(f(f(f(f(...)))))))))) ? yes % no se realiza el test de ocurrencia Nota: algunas implementaciones de Prolog, como por ejemplo SICStus Prolog, incorporan un predicado predenido especial que permite unicar con test de ocurrencia. En SICStus Prolog este predicado se denomina unify_with_occurs_check. ?- unify_with_occurs_check(X,f(X)). no % s se realiza el test de ocurrencia Funcin de seleccin. Selecciona siempre el literal ms a la izquierda. o o a Regla de ordenacin. Elige las clusulas de acuerdo con el orden en el que stas aparecen o a e en el programa. Estrategia de bsqueda: bsqueda en profundidad (se recuerda que esta estrategia es muy u u eciente pero tiene el inconveniente de que no es completa, esto es, puede conducir a una computacin innita an en el caso de que exista una solucin). o u o Por lo tanto, cuando, una vez cargado un programa lgico, se realiza una consulta, Prolog o construye el rbol de Resolucin SLD correspondiente, de acuerdo con la funcin de seleccin y a o o o la regla de ordenacin citadas, haciendo un recorrido en profundidad. As las posibles respuestas o , del sistema ante una consulta son las siguientes: Si todas las ramas del rbol SLD son ramas fallo, la respuesta del sistema ser no. a a Si el rbol SLD tiene alguna rama innita ms a la izquierda que cualquier posible rama a a xito, la reaccin del sistema depender de la implementacin concreta de Prolog que se e o a o est utilizando. Algunos sistemas, como por ejemplo SWI-Prolog, presentan un mensaje e de error. Otros, como es el caso de SICStus Prolog, no responden, por lo que es necesario interrumpir la ejecucin de la consulta mediante CONTROL-C (si se est usando SICStus o a Prolog a travs de Emacs, la composicin de teclas CONTROL-C deber efectuarse dos e o a veces seguidas). Una vez interrumpida la ejecucin, el sistema muestra por pantalla el o mensaje: Prolog interruption (h for help)? y acepta a continuacin una letra que determine la accin a seguir. Las posibles acciones o o se pueden consultar pulsando la tecla h, aunque lo ms habitual ser contestar con la a a letra a, cuya accin asociada es abortar la ejecucin de la consulta. o o En otro caso (es decir, cuando el rbol de Resolucin tiene por lo menos una rama xito a o e ms a la izquierda que cualquier posible rama innita): a - Si la consulta realizada no tiene variables (o las que tiene son annimas), la respuesta o del sistema ser yes, terminndose as la ejecucin de la consulta. a a o - Si la consulta realizada tiene alguna variable no annima, el sistema muestra por o pantalla los valores de las variables que se corresponden con la primera rama xito e encontrada al buscar en profundidad en el rbol de Resolucin, y queda a la espera a o de nuevas instrucciones por parte del usuario: 12

si se introduce un retorno de carro, el sistema contesta yes y abandona la bsqueda de posibles nuevas soluciones. u si se introduce un punto y coma seguido de un retorno de carro, el sistema continua la bsqueda de nuevas soluciones en el rbol de Resolucin, con lo que el proceso u a o se vuelve a repetir, dependiendo la respuesta del resultado de la bsqueda (no u si termina de recorrer el rbol sin encontrar ninguna nueva solucin ni ninguna a o rama innita, computacin innita si encuentra una rama innita o valor de las o variables correspondientes en caso de encontrarse otra solucin). o Como ya se coment en el tema anterior, resulta claro que tanto el orden en el que aparecen o las clusulas en los programas como el orden de los literales dentro de las clusulas pueden a a inuir no slo en el orden en el que aparecen las soluciones sino tambin en la terminacin de o e o las consultas que se realizan. e a Ejemplo: Considrese el siguiente programa (ancestros.pl), que incluye, adems de un predicado progenitor(X,Y) que es cierto cuando X es progenitor de Y , cuatro versiones distintas del predicado ancestro(X,Y), cierto cuando X es un ancestro de Y . Las cuatro versiones var an dependiendo del orden de sus clusulas y del orden en el que se colocan los literales dentro de a ellas. % progenitor(?X, ?Y): cierto si X es progenitor de Y progenitor(pepa, pepito). progenitor(pepito, pepin). % ancestro(?X, ?Y): cierto si X es un ancestro de Y % VERSIN 1 O ancestro1(X, Y) :- progenitor(X, Y). ancestro1(X, Y) :- progenitor(X, Z), ancestro1(Z, Y). % VERSIN 2 O ancestro2(X, Y) :- progenitor(X, Z), ancestro2(Z, Y). ancestro2(X, Y) :- progenitor(X, Y). % VERSIN 3 O ancestro3(X, Y) :- progenitor(X, Y). ancestro3(X, Y) :- ancestro3(Z, Y), progenitor(X, Z). % VERSIN 4 O ancestro4(X, Y) :- ancestro4(Z, Y), progenitor(X, Z). ancestro4(X, Y) :- progenitor(X, Y). Aunque las cuatro deniciones anteriores del predicado ancestro son iguales desde el punto de vista lgico, su comportamiento en Prolog es distinto, ya que darn lugar a rboles de o a a Resolucin distintos. Por ejemplo, si se intenta averiguar de quin es ancestro pepa, resulta lo o e siguiente (comprubense estos resultados mediante la construccin de los rboles de resolucin e o a o SLD correspondientes): 13

Consulta con ancestro1: ofrece las dos posibles soluciones y termina. ?- ancestro1(pepa, D). D = pepito ? ; D = pepin ? ; no Consulta con ancestro2: ofrece las dos posibles soluciones (en orden inverso al caso anterior) y termina. ?- ancestro2(pepa, D). D = pepin ? ; D = pepito ? ; no Consulta con ancestro3: ofrece las dos posibles soluciones, en el mismo orden que ancestro1, pero si se piden ms soluciones la consulta no termina. a ?- ancestro3(pepa, D). D = pepito ? ; D = pepin ? ; % el sistema entra en un bucle, que se interrumpe con CTRL-C CTRL-C Prolog interruption (h for help)? a {Execution aborted} Consulta con ancestro4: no produce ninguna solucin, porque entra directamente en o una rama innita. ?- ancestro4(pepa, D). % el sistema entra en un bucle, que se interrumpe con CTRL-C CTRL-C Prolog interruption (h for help)? a {Execution aborted} Aunque no existe ninguna regla general que establezca el orden ptimo de las clusulas ni el o a orden ptimo de los literales dentro de ellas, s suelen ser recomendables los siguientes principios o bsicos, basados en la idea de hacer antes lo ms sencillo: a a 1. Colocar las clusulas que expresan las condiciones de parada de la recursividad antes que a las otras (esto se cumple en las versiones 1 y 3 del ejemplo anterior). 2. Evitar las reglas con recursin a la izquierda, es decir, las reglas tales que el primer literal o de su cuerpo es una llamada recursiva al mismo predicado de la cabeza de la regla (las versiones 3 y 4 del ejemplo anterior presentan recursin a la izquierda). o De las cuatro versiones del ejemplo anterior, la unica que cumple estas dos recomendaciones es la primera. Es por otro lado necesario evitar deniciones circulares del estilo: 14

progenitor(X,Y) :- hijo(Y,X). hijo(A,B) :- progenitor(B,A). puesto que cualquier consulta a uno de los dos predicados anteriores provocar necesariamente a un bucle innito.

4.

Predicados Predenidos

En el apartado anterior se ha resumido el funcionamiento del lenguaje Prolog desde el punto de vista del paradigma de la Programacin Lgica. Sin embargo, las facilidades descritas no o o son sucientes para obtener un lenguaje de programacin util en la prctica: por ejemplo, o a todo lenguaje de programacin real necesita facilidades para leer y/o escribir o mecanismos o ecientes para realizar operaciones aritmticas. Para ello, el lenguaje Prolog incorpora toda una e serie de predicados del sistema o predicados predenidos (system or built-in predicates) que ofrecen al usuario facilidades como las citadas as como otro tipo de funcionalidades extra-lgicas o o meta-lgicas. Estos predicados no pueden ser redenidos por el programador. o En lo que sigue se describen slo algunos de estos predicados predenidos, en concreto los reo lacionados con la realizacin de operaciones aritmticas, ciertos predicados para entrada/salida o e y el predicado de control denominado corte.

4.1.
4.1.1.

Aritmtica e
Operadores aritmticos e

Prolog tiene predenidos los operadores aritmticos ms habituales, mediante los que se pueden e a formar expresiones aritmticas. A continuacin se enumeran algunos de los ms importantes: e o a X+Y X-Y X*Y X/Y X//Y X mod Y abs(X) sqrt(X) log(X) suma de X e Y X menos Y producto de X por Y cociente real de la divisin de X por Y o cociente entero de la divisin de X por Y o resto de la divisin entera de X por Y o valor absoluto de X ra cuadrada de X z logaritmo neperiano de X

Tngase en cuenta que los operadores anteriores permiten simplemente construir expresiones e aritmticas, pero stas no son ms que estructuras (trminos compuestos) que no representan e e a e ningn valor. Por ejemplo, la expresin 3+5 no es ms que el trmino compuesto +(3,5) escrito u o a e en notacin inja. As no es posible hacer consultas del estilo ?- 3+5., puesto que + no o , es un predicado, y si se hiciese la consulta ?- 3+5 = 8., la respuesta de Prolog ser no, a dado que el trmino compuesto +(3,5) no es unicable con el trmino constante 8. e e Para poder evaluar expresiones aritmticas en Prolog hay que utilizar los predicados aritmticos e e que se describen a continuacin. o 15

4.1.2.

Predicados aritmticos e

Los predicados aritmticos predenidos de Prolog se utilizan para evaluar expresiones aritmtie e cas. El ms habitual es el predicado predenido is, que se usa en notacin inja de la siguiente a o forma: X is Y Si Y es una expresin aritmtica, sta se evala y el resultado o e e u se intenta unicar con X.

A la hora de usar este predicado hay que tener en cuenta las siguientes consideraciones: 1. Su uso puede dar lugar a un error en los dos siguientes casos: a) cuando la parte derecha no es una expresin aritmtica: o e ?- X is a+1. {DOMAIN ERROR: _157 is a+1 - arg 2: expected expression, found a} b) cuando la parte derecha es una expresin aritmtica pero no se puede evaluar: o e ?- X is 4*Z. {INSTANTIATION ERROR: _157 is 4*_155 - arg 2} 2. Salvo en los casos anteriores, el resultado del predicado depender de si la parte izquierda a unica o no con el resultado obtenido al evaluar la parte derecha: ?- X is sqrt(4). X = 2.0 ? yes ?- 5 is 2+3. yes ?- X is 5, Y is X+1. X = 5, Y = 6 ? yes ?- 3+5 is 3+5. no

La respuesta negativa obtenida en el ultimo ejemplo se debe a que la expresin 3+5 de o la parte izquierda (recurdese que se trata simplemente del trmino compuesto +(3,5)) e e no es unicable con el entero 8, resultante de evaluar la parte derecha. Adems del predicado anterior, Prolog incorpora otros predicados comunes para comparaciones a aritmticas, aunque en algunos casos con una notacin distinta a la habitual: obsrvense en e o e particular los s mbolos para la igualdad/desigualdad (que no pueden ser los habituales = y \= puesto que stos se utilizan para la unicacin) y la comparacin menor o igual, que se escribe e o o al revs de lo que suele ser normal en otros lenguajes de programacin (<=). e o X X X X X X =:= Y =\= Y < Y =< Y > Y >= Y cierto cierto cierto cierto cierto cierto si si si si si si los valores numricos de X e Y son iguales e los valores numricos de X e Y son distintos e el valor numrico de X es menor que el de Y e el valor numrico de X es menor o igual que el de Y e el valor numrico de X es mayor que el de Y e el valor numrico de X es mayor o igual que el de Y e

El funcionamiento de estos predicados es similar al del predicado is: producirn un error a en caso de que alguno de los dos argumentos no sea una expresin aritmtica o, a pesar de o e 16

serlo, no se pueda evaluar. En caso contrario, el sistema evala las dos expresiones aritmticas u e y devuelve el resultado de la comparacin solicitada. o ?- X+3 < sqrt(4). .. ERROR: .. 4.1.3. ?- 3+5 =:= 8. yes ?- 1+ 5 > abs(-8). no ?- 3 =\= 3*a. .. ERROR: ..

Programas aritmticos en Prolog e

En el tema anterior, relativo a la Programacin Lgica general, se estudiaron varios programas o o lgicos aritmticos, como por ejemplo los programas para el clculo de la suma y el factorial o e a de nmeros naturales. Se trataba en ambos casos de programas lgicos denidos, por lo que u o basta con adaptar su sintaxis para obtener los correspondientes programas en Prolog (vase el e apartado 3.1.2 de este documento). Los programas aritmticos del estilo de los anteriores se pueden considerar programas lgicos e o puros, puesto que estn denidos utilizando exclusivamente propiedades lgicas, y tienen dos a o caracter sticas principales: - Son, por un lado, programas sencillos y verstiles. Recurdese en particular cmo pueden a e o utilizarse para varios cometidos distintos -por ejemplo el programa de la suma tambin e sirve para restar- ya que cualquiera de sus argumentos puede usarse tanto de entrada como de salida (vanse los ejemplos de consultas dados en el apartado 3.1.3). e - Son tambin, sin embargo, incmodos de utilizar en la prctica y poco ecientes. Su incoe o a modidad proviene del hecho de que los nmeros naturales se deben manipular mediante u la funcin sucesor, y la ineciencia se debe al clculo recursivo utilizado para resolver o a operaciones aritmticas elementales. e Una alternativa evidente para mejorar la comodidad y la eciencia de estos programas es reemplazarlos por otros que hagan uso de las facilidades aritmticas ofrecidas por Prolog, tanto en e lo que se reere al uso de sus constantes numricas como al uso de los operadores y predicados e aritmticos mencionados ms arriba. As si se desease disponer de un predicado para sumar e a , nmeros naturales, bastar con denirlo como sigue, utilizando simplemente el predicado de u a evaluacin is: o % suma(+X,+Y,?Z): cierto si Z es la suma de X e Y suma(X,Y,Z) :- Z is X+Y. Esta versin del predicado suma es claramente mucho ms cmoda (permite utilizar directao a o mente nmeros naturales en notacin decimal) y mucho ms eciente (utiliza la potencia de u o a clculo aritmtico del ordenador). Tiene sin embargo la desventaja respecto a la versin lgica a e o o pura de que pierde la versatilidad de sta. En efecto, como se puede ver en el comentario previo e a la denicin del nuevo predicado, ste, a diferencia del anterior, slo se puede usar cuando sus o e o dos primeros argumentos estn instanciados: si se intenta usar de otra forma se producir un a a error. Esto es debido a la utilizacin en el cuerpo de la regla del predicado predenido is, que, o como se vio antes, requiere que su parte derecha est instanciada. e 17

De forma similar, una denicin ms eciente -aunque menos elegante- del predicado factorial o a ser la siguiente: a % factorial(+X, ?Y): cierto si Y es el factorial de X. factorial(0, 1). factorial(X, Y) :X >0, X1 is X-1, factorial(X1, FactX1), Y is X*FactX1. Por el mismo motivo que antes, el predicado anterior slo se podr usar cuando el primer o a argumento est instanciado, es decir, el predicado es vlido para calcular factoriales, pero no e a sirve ya para averiguar si un nmero es o no el factorial de algn otro nmero. Esta restriccin u u u o no slo afecta al uso directo del predicado, sino tambin a su capacidad para ser usado en la o e denicin de otros: por ejemplo, el predicado es_factorial que se describi en el apartado o o 2.1.2. a partir de la versin lgica del predicado factorial ya no podr denirse utilizando o o a esta nueva versin. Obsrvese asimismo que en la nueva versin se ha introducido, antes de la o e o llamada recursiva, la comprobacin X>0, necesaria si se quiere evitar que se produzca una rama o innita en el rbol de Resolucin SLD correspondiente (constryanse como ejercicio los rboles a o u a de Resolucin asociados a una consulta concreta con y sin la comprobacin anterior). o o

4.2.

Entrada/Salida

El lenguaje Prolog ofrece toda una serie de predicados predenidos para la realizacin de operao ciones de entrada/salida. Se trata de predicados que no tienen sentido desde un punto de vista puramente lgico, sino que producen un efecto colateral (escritura/lectura de algn termino, o u apertura/cierre de un chero, etc). A continuacin se describen algunos de los predicados de o entrada/salida ms bsicos: a a open(+NombreFichero, +Modo, -Fichero) Si NombreFichero es un nombre de chero vlido, abre el chero correspondiente de a acuerdo con el modo especicado por Modo, y unica con Fichero el identicador del chero abierto. Los valores para el argumento Modo pueden ser: read para abrir el chero en modo lectura. write para abrir el chero en modo escritura (si el chero no existe, lo crea; si ya existe, su contenido se perder). a append para abrir el chero en modo escritura (si el chero no existe, lo crea; si ya existe, las operaciones de escritura se realizarn al nal del chero). a close(+Fichero) Cierra el chero asociado con el identicador Fichero. set_input(+Fichero) set_output(+Fichero)

Convierte al chero con identicador Fichero en el chero de lectura (escritura) actual. current_input(?Fichero) current_output(?Fichero)

Fichero es el chero de lectura (escritura) actual. 18

Nota: el chero por defecto, tanto para lectura como para escritura, es la pantalla, cuyo identicador es user. read(?Termino) read(+Fichero, ?Termino)

Lee el siguiente trmino (del chero de lectura actual o del chero especicado, previae mente abierto en modo lectura) y unica el resultado con Termino. El trmino debe acabar e con un punto y un retorno de carro. write(?Termino) write(+Fichero, ?Termino)

Escribe el trmino Termino en el chero de escritura actual o en el chero especicado e (previamente abierto en modo escritura). nl nl(+Fichero) Escribe un retorno de carro en el chero de escritura actual o en el chero especicado (previamente abierto en modo escritura). Ejemplos: Se incluyen a continuacin algunos ejemplos t o picos de predicados que realizan operaciones de entrada/salida (chero entrada-salida.pl): % pide_numero(-X) % X es un nmero ledo del fichero de lectura actual u pide_numero(X) :write(Introduzca un nmero: ), u nl, read(X). % escribe_cuadrado(+X) % escribe el cuadrado de X en el fichero de escritura actual escribe_cuadrado(X) :X2 is X*X, write(El cuadrado de ), write(X), write( es ), write(X2). % pide un nmero y escribe su cuadrado por pantalla u cuadrado :pide_numero(X), escribe_cuadrado(X). % imprime_lista(+Fichero, +L) % Si Fichero es un identificador de fichero y L es una lista, % escribe los elementos de L en el fichero, uno por lnea imprime_lista(_Fichero, []). imprime_lista(Fichero, [C|R]) :write(Fichero, C), nl(Fichero), imprime_lista(Fichero, R). 19

% imprime_lista(+L) % Si L es una lista, imprime por pantalla sus elementos, uno por lnea imprime_lista(L) :imprime_lista(user, L). % user es el identificador de la pantalla % pide una lista y la imprime en un fichero prueba_fich :write(Introduzca una lista: ), nl, read(Lista), open(prueba.txt, write, Prueba), imprime_lista(Prueba, Lista), write(la lista se ha escrito en el fichero prueba.txt), close(Prueba). A continuacin se reproduce la ejecucin de algunos de los predicados anteriores: o o ?- cuadrado. Introduzca un nmero: u |: 3. El cuadrado de 3 es 9 yes ?- imprime_lista([esto,es,una,lista]). esto es una lista yes ?- prueba_fich. Introduzca una lista: |: [h,o,l,a]. la lista se ha escrito en el fichero prueba.txt yes La ejecucin de este ultimo predicado tiene como efecto colateral la escritura de los elementos o de la lista [h,o,l,a] en el chero prueba.txt.

4.3.

Control: el corte

Los predicados de control son predicados predenidos que permiten al programador intervenir en el mecanismo de bsqueda de soluciones de Prolog. En este apartado se va a introducir u exclusivamente uno de ellos, el denominado predicado de corte. 20

4.3.1.

Denicin y propiedades o

El corte es un predicado predenido que se denota mediante un punto de exclamacin (!), no o tiene argumentos, y cuya evaluacin es siempre cierta. Se puede incluir, como un predicado o ms, en el cuerpo de las reglas o en las consultas (por ejemplo a :- b, c, !, d.). a Los cortes permiten al programador intervenir en el control del programa, puesto que su presencia hace que el sistema ignore ciertas ramas del arbol SLD correspondiente. En concreto, el efecto de los cortes en la construccin y recorrido de los rboles de resolucin SLD se produce o a o cuando el sistema llega a un nodo del rbol cuyo primer predicado es un corte, es decir, un nodo a de la forma ?- !,a1,..,an.. En estos casos ocurre lo siguiente (siendo N el nodo anterior): 1. El predicado de corte siempre se evala como cierto, por lo que el nodo N tendr un unico u a hijo, que ser igual a N pero sin el corte, es decir, ser de la forma ?- a1,..,an.. La a a expansin de este nodo se realiza igual que la expansin de cualquier otro nodo del rbol. o o a 2. Tanto para cada uno de los nodos ascendientes de N que contengan el corte como para el primer ascendiente que no lo contiene (sea N dicho nodo) se ignoran todas sus posibles ramas situadas ms a la derecha de la rama que lleva a N. a La siguiente gura ilustra lo anterior. Las ramas tachadas con una raya son aquellas que se ignoran como consecuencia del corte.

Ejemplo. Considrese el programa Prolog dado por las siguientes clusulas: e a a :- b, c. a :- .... b :- d, !, e. b. 21 b :- .... d. d :- .... e :- ....

       

      

La gura incluida a continuacin muestra el rbol de Resolucin SLD resultante al realizarse o a o la consulta ?-a. Las ramas tachadas son las que se deben ignorar debido al corte.

El efecto de la existencia de una regla de la forma a:-a1,..,ai,!,..,an se produce por lo tanto cuando el sistema llega a la evaluacin del corte, y consiste en hacer que todas las o opciones tomadas desde el momento en el que aparece la clusula objetivo conteniendo un corte a (incluida la decisin que lleva a la consideracin de esta clusula) hasta la evaluacin del corte o o a o sean obligatorias, eliminndose cualquier alternativa. En concreto: a En el momento de evaluar el corte, el sistema ya ha encontrado soluciones para los objetivos a1,..,ai, y no se considerarn otras alternativas para ninguno de ellos (en el ejemplo a anterior, no se consideran nuevas alternativas para el objetivo d). Tampoco se considerarn otras alternativas para el predicado responsable de la introduca cin del corte (en el ejemplo anterior, el predicado b). o El predicado de corte tiene dos ventajas fundamentales: Su utilidad bsica, dado que reduce el espacio de bsqueda de soluciones, es mejorar la a u eciencia de los programas, evitando la exploracin de partes del rbol de resolucin de o a o las que se sabe de antemano que no conducirn a ninguna nueva solucin. a o 22



 

  "        !     #

Por otro lado, el corte tambin permite aumentar la expresividad del lenguaje: su uso, nore malmente en combinacin con otros predicados predenidos, aporta nuevas construcciones o de gran utilidad, como por ejemplo la negacin por fallo nito. o Sin embargo, el corte es un predicado muy controvertido. Al tratarse de una herramienta de control (interviene en cmo se debe resolver el problema), su uso entra en clara contradiccin o o con los principios bsicos de la programacin lgica pura, que preconiza una separacin n a o o o tida entre la lgica del problema (responsabilidad del programador) y la forma de resolverlo (respono sabilidad del mecanismo de demostracin automtica). As el corte puede conducir a programas o a , lgicos dif o ciles de leer y de validar, y puede provocar muchos errores de programacin. o En denitiva, el predicado de corte de Prolog constituye una herramienta de carcter extraa lgico, muy potente pero que debe usarse con mucho cuidado y en casos muy concretos. o 4.3.2. Usos del corte. Ejemplos

Aunque el predicado de corte tiene usos muy variados (en general, en combinacin con otros o predicados predenidos de Prolog) uno de los ms habituales es la simulacin de estructuras a o condicionales de la forma: si b1 entonces c1 ; si no: si b2 , entonces c2 ; .... si no: si bn , entonces cn ; si no: c. En Prolog, este tipo de estructuras, con condiciones mutuamente excluyentes, se representan mediante un predicado denido por medio de n + 1 reglas, donde cada regla expresa una de las posibles formas de calcular el predicado: la regla i-sima expresa que el predicado es cierto e si no se cumple ninguna de las condiciones b1 , ..., bi1 anteriores y, adems, se cumplen las a condiciones bi y ci . El corte permite simplicar la representacin anterior y conseguir un uso ms eciente de este o a tipo de estructuras. Su representacin utilizando el corte es la siguiente: o a :a :.... a :a :b1, !, c1. b2, !, c2. bn, !, cn. c.

De esta forma se consigue que, en el momento en que se compruebe que se verica una cierta condicin bi, no se intente aplicar ninguna regla posterior. o A continuacin se describe el uso del corte mediante su aplicacin a varios ejemplos (todos ellos o o contenidos en el chero corte.pl).

23

Ejemplo 1: clculo de una funcin a o Supngase que se necesita denir un predicado en Prolog que permita calcular la siguiente o funcin f un: o 0, 1, f un(x) = 2, si x 10 si 10 < x 20 si x > 20

Una primera aproximacin para la resolucin del problema anterior es denir un predicado o o f(X,Y), cierto si Y es igual a f un(X), mediante las tres siguientes reglas: f(X,0) :- X =< 10. f(X,1) :- X>10, X =< 20. f(X,2) :- X > 20. La representacin anterior calcula correctamente los valores de la funcin f un, pero tiene el o o siguiente inconveniente. Supngase que se realiza la consulta ?- f(0,Z), Z>1.. La respuesta o de Prolog ser no, pero para llegar a dicha conclusin el sistema tiene que recorrer las 3 a o posibles ramas del rbol de Resolucin SLD correspondiente (dibjese como ejercicio dicho a o u rbol). Lo anterior es poco eciente, puesto que, al ser las tres reglas que describen el predicado a f mutuamente excluyentes, una vez que se ha encontrado una solucin con una de ellas no o tiene sentido probar con el resto. En efecto, la funcin que se est calculando tiene la siguiente o a estructura condicional: si X 10 entonces Y = 0; si no: si X 20, entonces Y = 1; si no: Y = 2. Por lo tanto, una forma de remediar la ineciencia anterior es utilizando el predicado de corte como se ha indicado al principio de este apartado: f(X,Y) :- X =< 10, !, Y=0. f(X,Y) :- X =< 20, !, Y=1. f(_X,2). Con esta nueva versin, la respuesta de Prolog a la consulta ?- f(0,Z), Z>1. ser tamo a bin no, pero ahora, gracias a la introduccin del corte en la primera regla, el sistema slo e o o tendr que explorar la primera rama del rbol SLD. a a Obsrvese que una forma ms cmoda para representar esta nueva versin consistir en, al e a o o a igual que en la primera versin, realizar la unicacin directamente en la cabeza de las reglas: o o f(X,0) :- X =< 10, !. f(X,1) :- X =< 20, !. f(_X,2).

24

Sin embargo, hay que destacar que esta ultima versin, a pesar de ser ms cmoda de escribir, o a o tiene el inconveniente de que no siempre es correcta, porque no funciona adecuadamente para ciertos usos del predicado: resuelve correctamente consultas de la forma ?- f(5,Z)., pero sin embargo no siempre funciona con consultas en las que ambos argumentos estn instanciados: a por ejemplo, la respuesta del sistema ante la consulta ?- f(0,2). ser armativa, cuando a deber ser evidentemente negativa. Este problema no se da en las versiones anteriores. a Ejemplo 2: clculo del mximo de dos nmeros a a u El procedimiento para calcular el mximo de dos nmeros naturales se puede implementar en a u Prolog mediante un predicado maximo(X,Y,Z), cierto si Z es el mximo de X e Y. Al igual que a en el ejemplo anterior, una primera versin para dicho predicado podr ser la siguiente: o a maximo(X,Y,X) :- X >= Y. maximo(X,Y,Y) :- X < Y.

Dado que las dos opciones son mutuamente excluyentes, una forma ms cmoda y eciente de a o expresar lo anterior es utilizando el corte: maximo(X,Y,Z) :- X >= Y, !, Z=X. maximo(_X,Y,Y).

Otra posibilidad, similar a lo que se coment en el ejemplo anterior, es modicar la versin o o anterior de forma que la unicacin se realice directamente en la cabeza de las clusulas: o a maximo(X,Y,X) :- X >= Y, !. maximo(_X,Y,Y).

Al igual que en el ejemplo anterior, resulta que esta ultima versin no puede usarse de cual o quier forma, porque con ciertas consultas puede dar lugar a resultados errneos: por ejemplo, o la respuesta del sistema ante la consulta ?-maximo(3,0,0). es armativa, cuando deber a ser evidentemente negativa. Ejemplo 3: pertenencia de un elemento a una lista La forma ms inmediata para representar en Prolog la pertenencia de un elemento a una lista a es la siguiente: pertenece(C, [C|_]). pertenece(C, [_|R]) :- pertenece(C,R). En la denicin anterior, las dos opciones no se consideran excluyentes, por lo que si un elemento o aparece varias veces en una lista, el predicado encontrar todas sus posibles ocurrencias. As a , 25

el predicado anterior podr utilizarse no slo para averiguar si un elemento pertenece a una a o lista determinada sino tambin para recorrer todos los elementos de una lista. Por ejemplo, la e respuesta del sistema ante la consulta pertenece(X,[a,b,c]). es la siguiente (comprubese e construyendo el rbol de resolucin SLD correspondiente). a o ?- pertenece(X,[a,b,c]). X = a ? ; X = b ? ; X = c ? ; no Una versin ms eciente del predicado anterior se consigue introduciendo un corte en el cuerpo o a de la primera regla, de forma que el predicado termine en el momento de encontrar la primera ocurrencia de un cierto elemento: pertenece(C, [C|_]) :- !. pertenece(C, [_|R]) :- pertenece(C,R). Con esto se consigue una versin determinista y ms eciente del predicado. Sin embargo, o a la introduccin del corte y la consiguiente poda del rbol de Resolucin SLD hace que el o a o predicado ya no se pueda usar, como con la versin anterior, para enumerar todos los elementos o de una lista. En efecto, ahora se tendr (comprubese construyendo el rbol de resolucin SLD a e a o correspondiente): ?- pertenece(X,[a,b,c]). X = a ? ; no

26

También podría gustarte