36
Introducción al lenguaje PROLOG 1 ÍNDICE Bibliografía recomendada. 2 1.- Introducción formal al lenguaje Prolog 3 2.- Cláusulas 5 3.- Términos 5 4.- Hechos 6 5.- Consultas 7 6.- Equiparación 7 7.- Reglas 8 7.1.- Recursividad 8 7.2.- Recursividad encubierta 9 7.3.- Eficiencia 9 7.4.- Directivas para mejorar la eficiencia 10 8.- Desigualdad 11 9.- Operadores lógicos y aritméticos 11 10.- Igualdad y asignación 12 11.- Modos de funcionamiento 13 12.- Eficiencia y corte 14 12.1.- Corte Verde 15 12.2.- Corte Rojo 15 13.- Fallo 17 14.- Negación 17 15.- Progamación Determinista/No Determinista 18 16.- Mecanismo de Resolución 19 17.- Listas 20 18- Ejercicios Básicos 23 Apéndice.- SWI_Prolog 31

Manual de Prolog

Embed Size (px)

Citation preview

Page 1: Manual de Prolog

Introducción al lenguaje PROLOG 1

ÍNDICE

Bibliografía recomendada. 2

1.- Introducción formal al lenguaje Prolog 3

2.- Cláusulas 5

3.- Términos 5

4.- Hechos 6

5.- Consultas 7

6.- Equiparación 7

7.- Reglas 8

7.1.- Recursividad 8

7.2.- Recursividad encubierta 9

7.3.- Eficiencia 9

7.4.- Directivas para mejorar la eficiencia 10

8.- Desigualdad 11

9.- Operadores lógicos y aritméticos 11

10.- Igualdad y asignación 12

11.- Modos de funcionamiento 13

12.- Eficiencia y corte 14

12.1.- Corte Verde 15

12.2.- Corte Rojo 15

13.- Fallo 17

14.- Negación 17

15.- Progamación Determinista/No Determinista 18

16.- Mecanismo de Resolución 19

17.- Listas 20

18- Ejercicios Básicos 23

Apéndice.- SWI_Prolog 31

Page 2: Manual de Prolog

Introducción al lenguaje PROLOG 2

BIBLIOGRAFÍA RECOMENDADA

� Bibliografía Básica

Prolog. Programming for artificial IntelligenceIvan BratkoEd. Addison-Wesley, 1994

The Art of PrologL.Sterling, E.ShapiroThe MIT Press, Cambridge, Massachusetts,1994

� Bibliografía Complementaria

Programming in PrologW.F.Clocksin, C.S.MellishSpringer-Verlag,1987

Prolog. Introducción a la Programación de sistemas expertosJ.M.Orenga y Ortega, J.P.Sánchez y BeltránEd. RAMA, 1987

Page 3: Manual de Prolog

Introducción al lenguaje PROLOG 3

1.- INTRODUCCIÓN FORMAL AL LENGUAJE PROLOG

PROLOG es un lenguaje declarativo e interpretado, en este tipo de lenguajes se representan losconocimientos sobre un determinado dominio y sus relaciones. A partir de ese conocimiento, sededucen las respuestas a las cuestiones planteadas, es decir se obtiene una inferencia.

El dominio lo constituye un conjunto de objetos.

El conocimiento se formaliza mediante un conjunto de relaciones que describen de formasimultánea las propiedades y sus interacciones.

Se declara el conocimiento disponible acerca de:

� OBJETOS:

� propiedades� relaciones

� REGLAS, que determinan interacciones lógicas del tipo: si ocurre q, r, s y tentonces P

� Ventaja:No hay que preocuparse de detalles de cómo resolver algo

� Desventaja:La resolución no siempre es eficiente.

Desde un punto de vista lógico, un programa Prolog está constituido por un conjunto decláusulas de Horn. Una cláusula de Horn tiene la forma general:

p(t1,t2,….,tn) :- p1(….),p2(….),…,pm(….) con m >= 0

Donde tanto p como las pi son símbolos predicados con sus argumentos entre paréntesis. A losargumentos de un predicado se les denomina Términos.

Las cláusulas de Horn son expresiones condicionales, siendo el símbolo “:-” el condicional osímbolo de la implicación (normalmente en lógica se utiliza el símbolo “��”). Así la cláusulaanterior podría leerse de la siguiente forma:

“SI p1(….) Y p2(….) Y … Y pm(….) ENTONCES p(t1,t2,…,tn)”

o bien podría leerse también:

“ Es cierto p(t1,t2,…,tn) SI es cierto p1(….) Y es cierto p2(….) Y … Y es ciertopm(….) “

Cuando m=0, la cláusula no tiene parte derecha, en este caso diremos que se trata de un hechoo afirmación.

p(t1,t2,…,tn).

Cuando la cláusula no tiene parte izquierda (o cabeza), se tiene una cláusula negativa opregunta, este tipo de cláusulas se utilizan para realizar la entrada/salida del programa:

?p1(….),p2(….),…,pm(….)

Un término ti puede ser:

� un átomo (número, constante)

Page 4: Manual de Prolog

Introducción al lenguaje PROLOG 4

� una variable� una estructura (functor): f(t1,t1,…tm)

donde los argumentos ti son a su vez términos

En la sintaxis estándar de Prolog (la que utilizaremos aquí se conoce como sintaxis deEdimburgo), los símbolos de átomos (constantes), functores y predicados comienzan con unaletra minúscula, los símbolos de variables comienzan con una letra mayúscula o con unsubrayado.

Un ejemplo de un programa Prolog sería el siguiente:

1. p(a,f(T,b)) :- q(Y,c,a),r(T,b).2. p(a,b).3. q(c,c,a).4. q(a,b,c) :- r(g(a,b),d).5. r(f(b,a),b).

Una computación en Prolog es un proceso de RESOLUCION LINEAL CON UNIFICACIÓNaplicado a una cláusula negativa (la pregunta) y al conjunto de cláusulas que constituyen elprograma. Así la cláusula negativa:

?p(a,X).

Tendría la siguiente interpretación:

¿Para qué valores de la variable X resulta cierto el predicado p(a,X). ?¿Para que valores de X se deduce p(a,X) del conjunto premisa que componen lascláusulas del programa?

Para resolver el objetivo ?p(a,X) aplicando resolución lineal, se intenta su unificación con laparte izquierda de alguna cláusula que contenga el mismo predicado/aridad. Si la unificación esposible, se sustituye el objetivo original por la lista de objetivos de la parte derecha de lacláusula utilizada en la unificación (con las sustituciones de variables que la unificaciónimplica). El proceso continúa con el primer objetivo de la lista resultante hasta quedesaparezcan todos los objetivos. Si en un momento dado resulta imposible resolver unobjetivo, se retrocede (backtracking) al objetivo más reciente con otras alternativas para suresolución, y se resuelve con la siguiente alternativa. Si no existen alternativas disponibles, elobjetivo de partida falla. Si se vacía la lista de objetivos, el objetivo queda resuelto.

El proceso desencadenado para el objetivo anterior sería el siguiente:

?p(a,X) resolviendo con 1, sustitución X=f(T,b)?q(Y,c,a),r(T,b) resolviendo con 3, sustitución Y=c?r(T,b) resolviendo con 5, sustitución T=f(a,b)?[ ] cláusula vacía

Luego el objetivo original se ha resuelto (es cierto) con X=f(f(a,b),b), que es el resultado (osalida) del cálculo realizado por el programa Prolog.La estrategia de resolución descrita para aplicar el principio de resolución y que suele utilizarseen el Prolog estándar, se denomina primero_en_profundidad (depth first), pues el árbol debúsqueda de la solución se recorre en profundidad (se intenta resolver en primer lugar elobjetivo más reciente de la lista de objetivos). El orden de utilización de las cláusulas pararesolver un objetivo en Prolog standard es el determinado por su aparición en el programa.

Nota: ¿Existe alguna otra solución a la resolución de ese objetivo?

Page 5: Manual de Prolog

Introducción al lenguaje PROLOG 5

2.- CLÁUSULAS

Un programa en Prolog está constituido por una secuencia de cláusulas. Estas cláusulas debenrepresentar todo el conocimiento necesario para resolver el problema.

Se pueden diferenciar tres tipos de Cláusulas:

� Hechos (afirmaciones), pueden representar:

� Objetos

� Propiedades de objetos.

� Relaciones entre objetos.

� Reglas.

� Consultas (cláusulas negativas).

Como se ha mencionado, un programa Prolog es una secuencia de cláusulas, donde cadacláusula puede estar formada por uno o varios predicados. Las cláusulas deben terminarobligatoriamente en punto.

3.- TÉRMINOS

En Prolog hay tres tipos de términos: CONSTANTES, VARIABLES Y ESTRUCTURAS

Tipo Comentarios Ejemplos Casos Especiales

Constante

Átomo En Minúsculas.

Nombre de:

� Objetos

� Propiedades

� Relaciones

luis

pedro

edad

color

padre

‘rey león’

Átomos especiales:- ?-

Número

Entero Sólo dígitos, +, - 63

Real Y punto decimal 365.2425

Variable Comienzan con Mayúscula ocon _

Suma X_Y

Variable anónima:_

Estructura Término compuesto por otrosTérminos

edad(luis, 63)

padre_de(luis, eva)

Page 6: Manual de Prolog

Introducción al lenguaje PROLOG 6

4.- HECHOS

Es el mecanismo básico para representar:

� objetos/personas/conceptos.

� propiedades de los objetos.

� relaciones entre los objetos.

Ejemplos:

padre(luis).

padre_de(luis, pedro).

azul(cielo).

Una relación viene definida por todas las instancias que aparecen con un predicado.

tipo de concepto Ejemplo aridad

objetos/personas/proposiciones luis

pedro

cielo

predicado/0

Propiedades padre

azul

predicado/1

Relaciones padre_de predicado/2, .../n

Los hechos pueden introducirse en la base de hechos del intérprete de Prolog mediante unaaserción:

?- assert(padre_de(luis, pepe)).yes.

Base de HECHOS. EJEMPLOS

amigos(pedro, antonio).amigos(pedro, flora).amigos(pedro, juan).amigos(pedro, vicente).

amigos(luis, felipe).amigos(luis, maria).amigos(luis, vicente).

amigos(carlos, paloma).amigos(carlos, lucia).amigos(carlos, juan).amigos(carlos, vicente).

amigos(fernando, eva).

amigos(fernando, pedro).

millonario(pedro).millonario(antonio).millonario(flora).

soltero(pedro).soltero(flora).soltero(eva).soltero(luis).

padre_de(carlos, fernando).padre_de(antonio, maria).padre_de(antonio, carlos).

Page 7: Manual de Prolog

Introducción al lenguaje PROLOG 7

5.- CONSULTAS

Es el mecanismo para extraer conocimiento del programa:

?- amigos(pedro, antonio).yes?- amigos(pedro, eva).no?- amigos(pedro, pepe).no

?- amigos(pedro, X).X= antonio ;X = flora ;

X = juan ;X = vicente ;no

?- amigos(antonio, pedro).no

?- novios(pedro, flora).WARNING Undefined predicatenovios/2

Ejemplo: Mi amigo, Vicente, busca amigos/as de mis amigos que sean millonarios/as y esténsolteros/as:

?- amigos(X, vicente), amigos(X, Y), millonario(Y), soltero(Y).X = pedro Y = flora ;No

� Una consulta estará constituida por una o varias metas que Prolog deberá resolver. Elintérprete de Prolog nos devuelve más soluciones si utilizamos el punto y coma “;” cuandono existen más soluciones que unifiquen con el objetivo, el intérprete contesta No.

6.- EQUIPARACIÓN

Este mecanismo permite comprobar si dos expresiones son equivalentes, produce comoresultado una sustitución de términos cuando esta es posible. Por ejemplo, si una variable estálibre y es equiparada con un valor numérico, se obtiene una instanciación (asignación) de lavariable con dicho valor.

Ejemplos:

amigos(pedro, vicente) y amigos(pedro, vicente)son equiparables.

amigos(pedro, vicente) y amigos(X, vicente)son equiparables. X = pedro.

amigos(pedro, Y) y amigos(X, vicente)son equiparables. X = pedro, Y = vicente.

amigos(X, X) y amigos(pedro, vicente)no son equiparables porque X = pedro, X = vicente no es posible.

En general, dos términos T1 y T2 son equiparables:

� T1, T2 son constantes => idénticas.� T1 o T2 es una variable => se equiparan instanciando el otro término a la variable.� T1, T2 son estructuras => los términos que los componen son equiparablesmanteniendo una instanciación de las variables coherente.

Page 8: Manual de Prolog

Introducción al lenguaje PROLOG 8

7 .- REGLAS

Permiten establecer relaciones más elaboradas entre objetos, por ejemplo, relacionesgeneralizadas o particularizadas, o relaciones causa-efecto. A continación, se muestran unconjunto de ejemplos en Prolog que permiten generalizar conceptos como el de padre, familiar,etc..

padre(X) :- padre_de(X, Y).

padre(X) :- padre_de(X, _).

hijo_de(X,Y) :- padre_de(Y, X).

hermanos(X,Y) :- padre_de(Z,X), padre_de(Z,Y). % ¡X = Y!

familiares(X, Y) :- padre_de(X, Y).familiares(X, Y) :- padre_de(Y, X).familiares(X, Y) :- hermanos(Y, X).

practica_suspendida(X) :- practica_copiada(X).practica_suspendida(X) :- practica_insuficiente(X).

practica_insuficiente(X) :- programa_no_funciona(X).practica_insuficiente(X) :- memoria_insuficiente(X).

peligro_de_inundacion(X) :- grifo_abierto(X), lleno_de_agua(X).

amigos_interesantes(X, Z) :- amigos(Y, X), amigos(Y, Z), millonario(Z), soltero(Z).% ¡Z = X!

7.1.-Reglas. RECURSIVIDAD

Para definir reglas más generales y flexibles, es necesario un mecanismo adicional. Para ello seutilizará el concepto de recursividad.

Para definir el concepto antecesor_de puede definirse de una forma iterativa:

antecesor_de(X,Y) :- padre_de(X, Y). % padreantecesor_de(X,Y) :- padre_de(X, Z), padre_de(Z, Y). % abueloantecesor_de(X,Y) :- padre_de(X, Z1), % bisabuelo

padre_de(Z1, Z2), padre_de(Z2, Y).

antecesor_de(X,Y) :- padre_de(X, Z1), % tatarabuelo padre_de(Z1, Z2), padre_de(Z2, Z3), padre_de(Z3, Y). ...

Este mecanismo no es eficiente, dado que no nos permite generalizar fácilmente el concepto deantecesor. Prolog permite utilizar definiciones recursivas, que resuelven el problema de formaelegante.

antecesor_de(X, Y) :- padre_de(X, Y).antecesor_de(X, Y) :- padre_de(X, Z), antecesor(Z, Y).

Page 9: Manual de Prolog

Introducción al lenguaje PROLOG 9

7.2.- Reglas. RECURSIVIDAD ENCUBIERTA

Uno de los peligros que conlleva la recursividad, es la de realizar definiciones circulares o queel intérprete de Prolog no sea capaz de resolver.

El ejemplo más simple de un caso problemático sería:

antecesor_de(X, Y) :- antecesor_de(X, Y).% que se puede reducir a la cláusula: P => P

Esta cláusula es declarativamente correcta, pero el intérprete de Prolog no podrá resolverlanunca y se quedará atrapado en un bucle infinito. De aquí se pueden observar otros casosproblemáticos, por ejemplo si se define la siguiente base de hechos sobre las amistades de unapersona:

amigos(pedro, antonio).amigos(pedro, flora)....amigos(fernando, pedro).

Si consideramos que el concepto amistad tiene una relación conmutativa, entoncesposiblemente nos interesaría definir la relación de amistad inversa o complementaria:

amigos(X, Y) :- amigos(Y, X). % ¡Peligro, recurrencia!

Esta definición aparentemente lógica provoca un error. La forma correcta de definirlo sería através de un nuevo predicado:

son_amigos(X, Y) :- amigos(X, Y).son_amigos(X, Y) :- amigos(Y, X).

7.3.- Reglas. EFICIENCIA

En lógica matemática no se impone un orden especial de las cláusulas y de los términos quecomponen los programas. Sin embargo, en Prolog es necesario cuidar el orden de las cláusulasdentro de un programa, debido a que el intérprete unifica la reglas en el orden secuencial en elque le han sido proprocionadas.Volviendo a la definición del predicado antecesor_de podemos ver que consta de dos cláusulas,una de las cuales posee dos metas (u objetivos). Esto permite generar cuatro definicionesdistintas de antecesor_de, permutando el orden de los términos y de las cláusulas.

antecesor1(X, Y) :- padre_de(X, Y).antecesor1(X, Y) :- padre_de(X, Z), antecesor1(Z, Y).

antecesor2(X, Y) :- padre_de(X, Z), antecesor2(Z, Y).antecesor2(X, Y) :- padre_de(X, Y).

antecesor3(X, Y) :- padre_de(X, Y).antecesor3(X, Y) :- antecesor3(Z, Y), padre_de(X, Z) .

antecesor4(X, Y) :- antecesor4(Z, Y), padre_de(X, Z) .antecesor4(X, Y) :- padre_de(X, Y).

Page 10: Manual de Prolog

Introducción al lenguaje PROLOG 10

En los ejemplos anteriores se obtienen resultados distintos.

� antecesor1 es la más eficiente y funciona siempre.� antecesor2 es menos eficiente.� antecesor3 sólo funciona para algunos casos.� antecesor4 no funciona nunca, siempre se queda atrapado en un bucle infinito.

Ejemplos:

?- antecesor3(antonio, carlos).% Verifica que la relación es cierta.

?- antecesor3(carlos, maria).% La relación es falsa, pero el programa no puede comprobarlo, quedará atrapado en un bucle% infinito.

?- antecesor3(X, Y).% Es capaz de imprimir algunos resultados, pero cuando la primera regla que define antecesor3% falle, quedará atrapado en un bucle infinito.

7.4.- Reglas. Directivas para mejorar la eficiencia.

El siguiente conjunto de directivas pueden utilizarse para lograr que la ejecución de nuestroprograma Prolog sea lo más eficiente posible.

� Primero los objetivos más sencillos

- Ordenación de cláusulas:1º las más específicas.2º las más generales (con recursividad).

Ejemplo:antecesor(X, Y) :- padre_de(X,Y).antecesor(X, Y) :- padre_de(X,Y), antecesor(Z,Y).

- Ordenación de términos dentro de una cláusula:1º los términos más específicos.2º los términos más generales (recursivos).

Ejemplo:antecesor(X, Y) :- padre_de(X,Y), antecesor(Z,Y).

� Acotar el espacio de búsqueda

amigos_interesantes(X, Z) :- % ¡Z = X!amigos(Y, X), amigos(Y, Z), millonario(Z), soltero(Z).

Sabiendo que los amigos son más frecuentes que los millonarios y solteros, resultará máseficiente a la hora de realizar la búsqueda cambiar el orden de las metas:

amigos_interesantes(X, Z) :- % ¡Z = X!millonario(Z), soltero(Z), amigos(Y, X), amigos(Y, Z).

Page 11: Manual de Prolog

Introducción al lenguaje PROLOG 11

8.- DESIGUALDAD

Para comprobar si dos términos son distintos, disponemos de diferentes operadores.

� Desigualdad \==Comprueba si dos términos son distintos. Por ejemplo, si dos variables tienen distintos valoresinstanciados.

� Desigualdad aritmética =\=Verifica la desigualdad numérica de dos expresiones.

Ejemplos:

hermanos(X,Y) :- padre_de(Z,X),padre_de(Z,Y),X \== Y .

amigos_interesantes(X, Z) :- millonario(Z), soltero(Z), amigos(Y, X), amigos(Y, Z), X \== Z .

no_nulo(X) :- X =\= 0.

9.- OPERADORES LOGICOS Y ARITMETICOS

Otros operadores de comparación aritmética son:

< ; > ; =< ; >=

Operadores y funciones aritméticas válidas en Prolog son:

+ - */ división real.// división entera.mod resto de división entera.abs valor absoluto.** potencia.

^ potencia.max valor máximo de dos.min valor mínimo de dos.round redondea al entero más próximo.integer trunca a la parte entera.float convierte en un valor real.

Page 12: Manual de Prolog

Introducción al lenguaje PROLOG 12

10.- IGUALDAD Y ASIGNACION

Disponemos de cuatro tipos de operadores de ‘igualdad’:

� Igualdad aritmética [=:=]. Comprueba la igualdad numérica de las expresiones argumento.

igual1(X, Y) :- X =:= Y.

� Identidad [==]. Comprueba si los términos argumento son idénticos.

igual2(X, Y) :- X == Y.

� Unificación [ = ]. Comprueba si los términos argumento son unificables (equiparables). Esequivalente a la asignación directa entre variables en un lenguaje procedimental. Da fallo si launificación no es posible.

igual3(X, Y) :- X = Y.

Una definición equivalente sería:

igual4(X,X).

� Asignación [is]. Evalúa la segunda expresión e intenta asignar el valor obtenido a lavariable. ¡No es conmutativo!

incremento(X,Y) :- Y is X+1.

Una definición similar a la de igualdad sería:

igual5(X, Y) :- X is Y.

Los operadores antes mencionados, aunque parten de conceptos muy distintos, poseencomportamientos similares, lo cuál puede inducir a errores. A continuación se muestra unatabla comparativa de todas las posibilidades existentes.

Operador =:= == = = isEjemplo igual1 igual2 igual3 igual4 igual5Igual?(3,3). yes yes yes yes yesIgual?(1,3). no no no no noIgual?(1+2,3). yes no no no noIgual?(3,1+2). yes no no no yesIgual?(X,1+2). * no X=1+2 X=1+2 X=3Igual?(1+2,X). * no X=1+2 X=1+2 *Igual?(3,X). * no X=3 X=3 *Igual?(X,3). * no X=3 X=3 X=3Igual?(‘hola’,’hola’). ** yes yes yes yesIgual?(1.0,1). yes no no no no***Igual?(1,1.0). yes no no no yes***Igual?(1.0,1.0). yes yes yes yes no***Igual?(1.1,1.1). yes yes yes yes yes***

* Excepción: Variable X libre.** Error: ‘hola’ no es función (o expresión) válida.*** Prolog tiene tendencia a convertir valores reales a enteros. En el segundo argumento

del operador is detecta que se puede convertir en entero.

Page 13: Manual de Prolog

Introducción al lenguaje PROLOG 13

11.- MODOS DE FUNCIONAMIENTO

Un predicado puede ser utilizado con diversos tipos de argumentos, pero no siempre estágarantizado que funcione. Los tipos de argumentos más comunes son:

� Términos (constantes o variables instanciadas). Representados con +� Variables libres. Representado con -� Cualquiera de los dos. representado con ?

Posibilidades:

igual1(X, Y) :- X =:= Y.igual1(constante, constante) funciona ==> igual1(+, +)igual1(vlibre, constante) no funcionaigual1(constante, vlibre) no funcionaigual1(vlibre, vlibre) no funciona

Resumen : igual1(+,+).————

igual4(X,X).igual4(constante, constante) funciona ==> igual4(+, +)igual4(vlibre, constante) funciona ==> igual4(-, +)igual4(constante, vlibre) funciona ==> igual4(+, -)igual4(vlibre, vlibre) funciona ==> igual4(-, -)

Resumen : igual4(?, ?)————

igual5(X, Y) :- X is Y.igual5(constante, constante) funciona ==> igual5(+, +)igual5(vlibre, constante) funciona ==> igual5(-, +)igual5(constante, vlibre) no funcionaigual5(vlibre, vlibre) no funciona

Resumen : igual5(?,+).————

Se puede incluir más información sobre el tipo concreto de argumento, por ejemplo: número,expresión, carácter,...

igual1(X, Y) :- X =:= Y. Resumen : igual1(+,+).Los argumentos deben ser expresiones numéricas:

==> igual1(+expresión,+expresión).————

igual4(X,X). Resumen : igual4(?, ?)Los argumentos pueden ser cualquier tipo de término:

==> igual4(?término,?término).————

igual5(X, Y) :- X is Y. Resumen : igual5(?,+).El primer argumento pueden ser una variable libre o constante numérica, el segundo debe seruna expresión numérica:

==> igual5(?número,+expresión).Es conveniente incluir información de este tipo en los programas cada vez que se define unpredicado.

Page 14: Manual de Prolog

Introducción al lenguaje PROLOG 14

12.- EFICIENCIA Y CORTE

Supongamos que se desea programar en Prolog la siguiente función matemática:

Función escalón

0

2

4

-6 -3 0 3 6 9

��

��

��

x

x

x

xf

6 ,4

63 ,2

3 ,0

)(

Una posible solución (la más intuitiva) sería la mostrada a continuación:

f(X,Y) :- X < 3, Y is 0. % f(+,?)f(X,Y) :- 3 =< X, X < 6. Y is 2.f(X,Y) :- 6 =< X, Y is 4.

Se puede optimizar adelantando la equiparación:

f(X,0) :- X < 3. % f(+,?)f(X,2) :- 3 =< X, X < 6.f(X,4) :- 6 =< X.

Si analizamos el problema, resulta que las soluciones mostradas son poco eficientes debido aque se hacen demasiadas comprobaciones. Por ejemplo, al intentar calcular ?-f(2,Y),Y =:= 2.Se comprueban las 3 cláusulas cuando sólo haría falta comprobar una.

f(2,Y), Y =:= 2.

f(X,4) :- X>=6.

No.

f(X,0) :- X < 3.

f(X,2) :- 3=<X, X<6.

¡fallo!

Y=0, Y=:=2.X=2, X<3,

¡fallo!

X=2, X>=3.Y=2,

¡fallo!

X=2, X>=6.Y=4,

Page 15: Manual de Prolog

Introducción al lenguaje PROLOG 15

12.1.- CORTE VERDE

Existe un predicado que capaz de ‘cortocircuitar’ la búsqueda una vez que es evaluado: elcorte, representado con el símbolo de admiración “!”.El corte, es un predicado que siempre seevalúa como cierto y que impide que se continúen evaluando el resto de reglas.

f(X,0) :- X < 3, !. % f(+,?)f(X,2) :- 3 =< X, X < 6, !.f(X,4) :- 6 =< X.

Basándonos en un programa semánticamente correcto hemos añadido el operador de corte paraobtener un programa más eficiente. => Corte Verde.

Esto quiere decir que si eliminamos el predicado de corte, el programa funcionará también,pero tendrá el defecto de carecer de una interpretación lógica o declarativa. Es necesario unainterpretación procedimental para entender este predicado.

f(2,Y), Y =:= 2.

f(X,4) :- X>=6.

No.

f(X,0) :- X < 3, !.

f(X,2) :- 3=<X, !, X<6.

¡fallo!

Y=0, Y=:=2.X=2, X<3, !,

¡fallo!

X=2, X>=3.Y=2,

¡fallo!

X=2, X>=6.Y=4,

12.2.- CORTE ROJO

Partiendo del ejemplo anterior:

f(X,0) :- X < 3, !.f(X,2) :- 3 =< X, X < 6, !.f(X,4) :- 6 =< X.

Se puede cuestionar porqué debemos comprobar algunas condiciones en el programa, si el cortelas hace superfluas. En el ejemplo, la segunda cláusula sólo se alcanza cuando X>3 y la terceracuando X>6. Podemos reescribir el programa de la siguiente forma:

f(X,0) :- X < 3, !.f(X,2) :- X < 6, !.f(X,4).

Curiosamente deja de funcionar en modo f(+,+), por ejemplo el caso f(0,4) daría cierto. ¿Qué seha hecho mal?. El problema es que el nuevo programa se basa en un programa semánticamenteincorrecto, si eliminásemos el corte, observaríamos que al eliminar el operador de corteobtenemos un programa incorrecto:

f(X,0) :- X < 3. % ¡MAL!f(X,2) :- X < 6.f(X,4).

Page 16: Manual de Prolog

Introducción al lenguaje PROLOG 16

¡Este tipo de corte (Corte Rojo) debe emplearse con sumo cuidado!

Partiendo del ejemplo anterior:

f(X,0) :- X < 3, !. % f(+,-)f(X,2) :- X < 6, !.f(X,4).

El motivo de perder el modo f(+,+) es debido a una interacción poco obvia entre laequiparación, las condiciones y el corte. El programa realmente debería ser:

f(X,Y) :- X < 3, !, Y is 0. % f(+,?)f(X,Y) :- X < 6, !, Y is 2.f(X,Y) :- Y is 4.

No obstante este programa sigue basándose en un programa semánticamente incorrecto; aleliminar nuevamente el operador de corte se sigue obteniendo un programa incorrecto:

f(X,Y) :- X < 3, Y is 0. % ¡MAL!f(X,Y) :- X < 6, Y is 2.f(X,Y) :- Y is 4.

?- f(2, X).X = 0 ;X = 2 ;X = 4

Supongamos que se desea programar otra función matemática en Prolog::

a

Función rampa

-2

-1

0

1

2

3

4

5

6

-3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 g x

x x

x x

x x

( )

,

,

,

� �

��

��

3 3

3 3 6

9 6

Una primera solución, sin utilizar el corte podría ser:

g(X,Y) :- X < 3, Y is 3 - X.g(X,Y) :- 3 =< X, X < 6, Y is X - 3.g(X,Y) :- X >= 6, Y is 9 - X.

Incluyendo el corte se obtendría:

g(X,Y) :- X < 3, !, Y is 3 - X.g(X,Y) :- 3 =< X, X < 6, !, Y is X - 3.g(X,Y) :- X >= 6, Y is 9 - X.

Page 17: Manual de Prolog

Introducción al lenguaje PROLOG 17

Si se trazan algunos ejemplos sencillos se pueden observar los posibles casos que puedenpresentarse con esta solución:

1º se evalúa la primera cláusula, por ejemplo para g(4,Z). El primer término es falso: X<3. ��El intérprete pasa a verificar la segunda cláusula.

2º El primer término es cierto y se aplica el corte, pero el último término es falso. Por ejemplo,en g(2,3). �� El intérprete retrocede con falso; debido al corte no se intenta verificar otracláusula. El intérprete responde: No.

3º El primer término es cierto y se aplica el corte, el último término es cierto o equiparable. Porejemplo, en g(2,1) o g(2, Z). �� El intérprete retrocede con cierto; debido al corte no se intentaverificar otra cláusula. El intérprete responde: Sí.

13.- FALLO

fail (fallo) es un predicado que siempre produce fallo. Es útil cuando queremos detectar casosexplícitos que invalidan un predicado.

Ejemplo: Programa que simule una puerta lógica nand de 7 entradas (equivale a not and).Esta puerta lógica sólo da falso en su salida cuando todas las entradas son ciertas (en este casovamos a suponer que entrada=1 equivale a cierto).

nand7(0, _, _, _, _, _, _).nand7(_, 0, _, _, _, _, _).nand7(_, _, 0, _, _, _, _).nand7(_, _, _, 0, _, _, _).nand7(_, _, _, _, 0, _, _).nand7(_, _, _, _, _, 0, _).nand7(_, _, _, _, _,_, _0).

La solución queda más sencilla si se utiliza el fallo:

nand7(1, 1, 1, 1, 1, 1, 1) :- !, fail.nand7(_, _, _, _, _, _, _).

Nota: fail suele utilizarse en combinación con el corte.

14.- NEGACIÓN

Existe un predicado de negación en Prolog (not) que está implementado como negación porfallo, esto quiere decir que se evalúa como falso cualquier cosa que Prolog sea incapaz deverificar que su predicado argumento es cierto.

no_nulo(X) :- not (X =:= 0).

Otros ejemplos:

saldo_cuenta(maria,1000).saldo_cuenta(flora,3000000).saldo_cuenta(antonio,2000000).padre_de(antonio, maria).millonario(X) :- saldo_cuenta(X, Y), Y > 1000000.pobre(X) :- not millonario(X).

Page 18: Manual de Prolog

Introducción al lenguaje PROLOG 18

?- millonario(X).X = flora ;X = antonio?- pobre(X).No.

persona_interesante(X) :- not padre_de(X, _), millonario(X).?- persona_interesante(X).No.?- persona_interesante(flora).Yes.

persona_interesante(X) :- millonario(X), not padre_de(X, _).?- persona_interesante(X).X = flora

pudiente(X) :- not pobre(X). % ¡No equivale a millonario!

15.- PROGRAMACION DETERMINISTA/NO DETERMINISTA

Los programas que se han visto hasta ahora definían una serie de situaciones que podían darse,y qué había que hacer en cada caso (programa determinista).

Ejemplo: programa para calcular el mínimo de dos números:

min(X,Y, Z) :- X < Y, Z is X. % min(+,+,?)min(X,Y, Z) :- X >= Y, Z is Y.

Ejemplo: dados tres hechos que describen los lados de un triángulo, escribir un programa quedevuelva las longitudes ordenadas de forma ascendente: ordena(-,-,-).

lado(a, 5).lado(b, 3).lado(c, 4).

ordena2(X,Y, X1,Y1) :- X<Y, X1 is X, Y1 is Y.ordena2(X,Y, X1,Y1) :- X>=Y, X1 is Y, Y1 is X.

ordena3 (X, Y, Z) :- lado(a, X1), lado(b, Y1), lado(c, Z1),ordena2(X1,Y1, X2,Y2),ordena2(X2,Z1, X,Z2),ordena2(Y2,Z2, Y,Z).

Para obtener un programa no determinista, lo que se puede plantear es; generar de formacombinatoria soluciones posibles y comprobar si son correctas. El método de búsqueda deProlog se encarga de retroceder cuando una solución no es válida.

ordena3 (X, Y, Z) :- lado(Xn, X), lado(Yn, Y), lado(Zn, Z),Xn \= Yn, Xn \= Zn, Yn \= Zn, X =< Y, Y =< Z.

Page 19: Manual de Prolog

Introducción al lenguaje PROLOG 19

16.- MECANISMO DE RESOLUCION

Como se explicó en la introducción, Prolog utiliza un mecanismo conocido como Resoluciónlineal con unificación para resolver las preguntas que se le plantean (cláusulas negativas), elmecanismo consiste en realizar una búsqueda en profundidad y retroceso (backtracking)tratando de unificar la cláusula objetivo con las contenidas en la base de hechos, hasta lograralcanzar la cláusula vacía. A continuación, se muestra de forma simplificada el algoritmoutilizado:

1. Se extraen las metas de la consulta y se introducen en orden en la lista demetas.

2. Se realiza una llamada recursiva al procedimiento de búsqueda con la lista demetas pendientes.

3. Si se encuentra solución, imprimirla4. Si no hay solución, imprimir false.

PROCEDIMIENTO DE BÚSQUEDA:1º Se extrae la primera meta eliminándola de la lista.2º Mientras sea posible:3º Buscar un hecho o una regla que satisfaga la meta.4º Si se encuentra:5º Si ListaMetas no está vacía llamar al procedimiento de búsqueda de forma

recursiva con ListaMetas y las variables equiparadas.6º Si ListaMetas está vacía provocar un retorno con las metas satisfechas y las

variables equiparadas.7º Si hay solución de las metas al volver de la llamada en 5º, provocar un retorno

con las soluciones.8º En caso contrario, seguir en bucle, paso 3º.9º Si no se ha encontrado solución alguna, provocar un retroceso, e.d. un retorno

sin solución.

Ejemplo. Base de hechos:

primoroso(zorro).primoroso(oso).amoroso(oso).astuto(zorro).

Consulta:

?-primoroso(X), amoroso(X).

Mecanismo de resolución:

ListaMetas = { primoroso(X), amoroso(X) }Resultado = Proc_Busqueda (ListaMetas, X)

Pmeta = primera (ListaMetas) = primoroso(X)ListaMetas = resto (ListaMetas) = { amoroso(X) }Mientras sea posible:

Primer hecho: ¿primoroso(zorro) satisface PMeta?, si; ==>Resultado = Proc_Busqueda (ListaMetas)

Page 20: Manual de Prolog

Introducción al lenguaje PROLOG 20

PMeta = primera (ListaMetas) = amoroso(X), X = zorro.ListaMetas = resto (ListaMetas) = { }Mientras sea posible:

Primer hecho: ¿amoroso(oso) satisface PMeta?, no;Retroceso sin solución para amoroso(X).

Resultado = Proc_Busqueda (ListaMetas) = False.Siguiente hecho: ¿primoroso(oso) satisface PMeta?, si; ==>Resultado = Proc_Busqueda (ListaMetas, X = oso)

PMeta = primera (ListaMetas) = amoroso(X), X = oso.ListaMetas = resto (ListaMetas) = { }Mientras sea posible:

Primer hecho: ¿amoroso(oso) satisface PMeta?, si;ListaMetas vacia =>Provocar retorno con Solución { X = oso }

Provocar retorno con Solución { X = oso }Imprimir Solución X = oso.

17.- LISTAS

Una lista es una secuencia ordenada de elementos que pueden tener cualquier longitud. Loselementos de una lista puede ser cualquier tipo de términos (constantes, variables oestructuras), o incluso otra lista. Las listas en Prolog pueden representarse como un casoparticular de árbol, una lista está formada por dos elementos: la cabeza (primer elemento de lalista) y la cola (resto de elementos de la lista). Ambos elementos se consideran componentes dela estructura cuyo functor es el punto “.”

Ejemplos:

1. Lista con un único elemento “a”

Notación en Prolog � .(a,[ ])Representación gráfica � .

a [ ] %lista vacía

2. Lista con tres átomos “a,b,c”

Notación en Prolog � .(a,.(b,.(c,[])))Representación gráfica � .

a .b .

c [ ] %lista vacía

� Debido al frecuente uso de este tipo de estructura, Prolog permite una notación abreviadapara representar listas. Los elementos de la lista aparecen separados por comas, y la listacompleta aparece entre corchetes.

[a, b, c] Lista con los tres elementos a, b y c[ ] Lista vacía.

En la definición de predicados se pueden usar además variables y un separador:

[a | L] Lista con el elemento a en la cabecera y el resto en la variable L (cola).

Page 21: Manual de Prolog

Introducción al lenguaje PROLOG 21

[a, b | L] Lista con los elementos a y b en la cabecera y el resto en la variable L (cola).

[X | L] Lista con el primer elemento instanciado en la variable X y el resto en lavariable L (cola).

[X, Y | L] Lista con el primer elemento instanciado en la variable X, el segundo en Y y elresto en la variable L (cola).

� Ejemplos de predicados útiles en el manejo de listas.

1º.- Número de elementos de una lista:

longitud(Xs, N)

longitud([ ], 0).longitud([X | Xs], N) :- longitud(Xs, N1), N is N1+1.

2º.- Pertenencia a una lista:

pertenece(X, L)

% 1ª formapertenece(X, [ ]) :- fail.pertenece(X, [X|L]).pertenece(X, [Y|L]) :- X\=Y, pertenece(X, L).

% 2ª formapertenece(X, [X|L]).pertenece(X, [Y|L]) :- pertenece(X, L).

3º.- Creación de una lista a partir de dos listas (concatenar dos listas: Append).

concatenar(L1,L2,L3)

concatenar([ ], L, L).concatenar([X|C1],L2, [X|C3]) :- concatenar(C1,L2,C3).

4º.- Eliminación de un elemento X de una lista L1, como consecuencia se obtiene la lista L2 (seelimina la primera aparición del elemento).

elimina(X,L1,L2)

% 1ª formaelimina(X,[]) :- fail.elimina(X,[X|Cola],Cola).elimina(X,[Y|C1],[Y|C2]) :- elimina(X,C1,C2).

% 2ª formaelimina(X,[X|Cola],Cola).elimina(X,[Y|C1],[Y|C2]) :- elimina(X,C1,C2).

Page 22: Manual de Prolog

Introducción al lenguaje PROLOG 22

5º.- Eliminación de todas las apariciones de un elemento X en una lista L1, como consecuenciase obtiene la lista L2.

borrar(X,L1,L2)

borrar(_,[ ],[ ]).borrar(X,[X|C],M) :- ! , borrar(X,C,M).borrar(X,[Y|L1],[Y|L2]) :- borrar(X,L1,L2).

6º.- Invertir todos los elementos de una lista.

invertir(L1,L2)

invertir([],[]).invertir([X|C],Z) :- invertir(C,C1),concatenar(C1,[X],Z).

� Ejemplos de unificación de listas.

Lista 1 Lista 2 Instanciaciones[X,Y,Z] [esto,es,prolog] X=esto, Y=es, Z=prolog

[mustang] [X|Y] X=mustang, Y=[][X,Y|Z] [cuando,harry,encontro,a,sally] X=cuando, Y=harry,

Z=[encontro,a,sally][X,busca,Z] [harry,Y,sally] X=harry, Y=busca, Z=sally[X,[actor,Z]] [cine,[Y,meg]] X=cine, Y=actor, Z=meg

[[el,Y]|Z] [[X,libro],esta,aquí] X=el, Y=libro, Z=[esta,aquí]

Si se tienen dudas de la posible unificación de dos listas o de términos en general, se puedeasegurar el resultado de la unificación utilizando el predicado interno “=” del intérprete deProlog.

Ejemplos:

?-[X,libro]=[lapiz,Y].X=lapizY=libroYes

?-[X,libro]=[Y,lapiz].No

Page 23: Manual de Prolog

Introducción al lenguaje PROLOG 23

18.- EJERCICIOS BÁSICOS

� Ejercicio 1

Enunciado: Programar en Prolog una cláusula que calcule el factorial de n.

Soluciones…Ejercicio 1

� Solución 1ª

factorial(0, 1).factorial(N, X) :-N1 is N - 1, factorial(N1, X1),X is X1 * N.

La solución anterior no funciona bien si le pasamos un número negativo, para evitar esteproblema podemos utilizar el fallo y el corte:

� Solución 2ª

factorial2(N, _) :- N < 0, fail.factorial2(0, 1).factorial2(N, X) :- N > 1, N1 is N - 1, factorial(N1, X1), X is X1 * N.

� Solución 3ª

factorial3(N, _) :- N < 0, !, fail.factorial3(0, 1) :- !.factorial3(N, X) :- N > 1, N1 is N - 1, factorial(N1, X1), X is X1 * N.

� Solución 4ª

factorial4(N, _) :- N < 0, !, fail.factorial4(0, 1) :- !.factorial4(N, X) :- N1 is N - 1, factorial(N1, X1), X is X1 * N.

Page 24: Manual de Prolog

Introducción al lenguaje PROLOG 24

� Ejercicio 2

Enunciado: Programar la siguiente función matemática en Prolog.

Función Sierra

-2-1012345678

-3 0 3 6 9 12

���

���

��

��

��

9

96 ,6

63 ,3

30 ,

0

)(

xnodefinida

xx

xx

xx

xnodefinida

xh

Soluciones…Ejercicio 2

� Solución 1ª

h(X,X) :- 0 =< X, X < 3.h(X,Y) :- 3 =< X, X < 6, Y is X - 3.h(X,Y) :- 6 =< X, X < 9, Y is X - 6.

En esta solución se emplea el predicado de corte y el de fallo para mejorar la eficiencia.

� Solución 2ª

h2(X,0) :- X < 0, !.h2(X,0) :- 9 =< X, !.h2(X,X) :- 0 =< X, X < 3, !.h2(X,Y) :- 3 =< X, X < 9, Z is X - 3, h(Z, Y).

� Solución 3ª

h3(X,0) :- X < 0, fail.h3(X,0) :- 9 =< X, fail.h3(X,X) :- X < 3, !.h3(X,Y) :- X < 6, !, Y is X - 3.h3(X,Y) :- X < 9, Y is X - 6.

� Solución 4ª

h4(X,0) :- X < 0, fail.h4(X,0) :- 9 =< X, fail.h4(X,X) :- X < 3, !.h4(X,Y) :- 3 =< X, X < 9, Z is X - 3, h(Z, Y).

Page 25: Manual de Prolog

Introducción al lenguaje PROLOG 25

� Ejercicio 3

Enunciado: Programación determinista/no determinista del ejemplo visto en el apartado 15.

Soluciones…Ejercicio 3

� Solución no determinista (más eficiente)

ordena3 (X, Y, Z) :- lado(Xn, X), lado(Yn, Y),Xn \= Yn, X =< Y,lado(Zn, Z),Xn \= Zn, Yn \= Zn,Y =< Z.

� Solución determinista

ordena2(X,Y, X,Y) :- X<Y.ordena2(X,Y, Y,X) :- X>=Y.

ordena3 (A,B,C X, Y, Z) :- ordena2(A,B, X1,Y1),ordena2(X1,C, X,Z1),ordena2(Y1,Z1, Y,Z).

� Solución no determinista

permuta2(X,Y, X,Y).permuta2(X,Y, Y,X).

permuta3(X,Y,Z, X,Y1,Z1) :- permuta2(Y,Z, Y1,Z1).permuta3(X,Y,Z, Y,X1,Z1) :- permuta2(X,Z, X1,Z1).permuta3(X,Y,Z, Z,X1,Y1) :- permuta2(X,Y, X1,Y1).

ordena3 (A, B, C) :- permuta3(A,B,C, X,Y,Z), X =< Y, Y =< Z.

Page 26: Manual de Prolog

Introducción al lenguaje PROLOG 26

� Ejercicio 4

Enunciado: Implementar la estructura de hechos en Prolog que nos permita trabajar yrepresentar datos estructurados. Para ello, se pide obtener una representación válida para untriángulo, donde podremos representar las tres coordenadas de los puntos que lo forman.

Soluciones…Ejercicio 4

triangulo(X1,Y1, X2,Y2, X3,Y3).triangulo(0,0, 3,1, 2,2).triangulo(v(0,0), v(3,1), v(2,2)).

v(X,Y) :- vertice(X,Y).

?- triangulo(v(X,Y), v(3,1), v(2,2)).X=0, Y=0

� Ejercicio 5

Enunciado: Escribir un programa procedimental que, dados tres valores: [a, b y c], responda sies posible construir un triángulo cuyos lados tengan longitud a, b y c.De ser así, deberá indicar también el tipo de triángulo: escaleno, isósceles o equilátero.

La caberecera que se definiría en Pascal sería:

FUNCTION TrianguloQ (X, Y, Z : REAL) : BOOLEAN ;...

Escribir un programa equivalente en Prolog.

trianguloq(A,B,C) ...

Soluciones…Ejercicio 5

� Solución en PASCAL

FUNCTION TrianguloQ (X, Y, Z : REAL) : BOOLEAN ;PROCEDURE Ordena3 (VAR X, Y, Z : REAL) ;

PROCEDURE Swap2 (VAR V1, V2 : REAL) ; (* Ordena2 *)VAR

AUX : REAL ;BEGIN

AUX := V1 ;V1 := V2 ;V2 := AUX

END;BEGIN

IF (X > Y) THEN Swap2 (X, Y) ;IF (X > Z) THEN Swap2 (X, Z) ;IF (Y > Z) THEN Swap2 (Y, Z) ;

END;

BEGINOrdena3 (X, Y, Z);IF (X > 0) AND (X + Y > Z) THEN (* Es_triangulo *)

BEGINIF (X = Z) THEN

Page 27: Manual de Prolog

Introducción al lenguaje PROLOG 27

WRITELN (‘Equilatero’);ELSE IF (X = Y) OR (Y = Z)

WRITELN (‘Isósceles’);ELSE

WRITELN (‘Escaleno’);RETURN (TRUE);

ENDELSE RETURN (FALSE);

END;

� Planteamiento 1º

En primer lugar, se plantean las condiciones necesarias para poder construir un triánguloT(a,b,c) a partir de las magnitudes a, b y c.

Condiciones previas para que T(a,b,c) sea triángulo: [a>0, b>0, c>0]Restricción necesaria para que T(a,b,c) sea triángulo:a+b>c si c>a,ba+c>b si b>a,cb+c>a si a>b,c

T(a,b,c) es equilátero sia = b = cT(a,b,c) es isósceles si se cumplea=c, b!=aa=b, c!=ac=b, a!=cT(a,b,c) es escaleno si se cumplena!=bb!=ca!=c

� Solución 1ª

lados_positivos(A,B,C) :- A>0, B>0, C>0.lados_adecuados(A,B,C) :- A=<C, B=<C, A+B>C.lados_adecuados(A,B,C) :- A=<B, C=<B, A+C>B.lados_adecuados(A,B,C) :- C=<A, B=<A, B+C>A.es_triangulo(A,B,C):- lados_positivos(A,B,C), lados_adecuados(A,B,C).equilatero(A,B,C) :- es_triangulo(A,B,C), A==B, A==C.isosceles(A,B,C) :- es_triangulo(A,B,C), A==C, A=\=B.isosceles(A,B,C) :- es_triangulo(A,B,C), A==B, B=\=C.isosceles(A,B,C) :- es_triangulo(A,B,C), B==C, B=\=A.escaleno(A,B,C) :- es_triangulo(A,B,C), A=\=B, B=\=C, A=\=C.trianguloq(A,B,C) :- equilatero(A,B,C), write(‘equilatero’).trianguloq(A,B,C) :- isosceles(A,B,C), write(‘isosceles’).trianguloq(A,B,C) :- escaleno(A,B,C), write(‘escaleno’).

� Solución 2ª

lados_positivos(A,B,C) :- A>0, B>0, C>0.lados_adecuados(A,B,C) :- A=<C, B=<C, A+B>C.lados_adecuados(A,B,C) :- A=<B, C=<B, A+C>B.lados_adecuados(A,B,C) :- C=<A, B=<A, B+C>A.es_triangulo(A,B,C):- lados_positivos(A,B,C), lados_adecuados(A,B,C).equilatero(A,B,C) :- A==B, A==C.isosceles(A,B,C) :- A==C, A=\=B.

Page 28: Manual de Prolog

Introducción al lenguaje PROLOG 28

isosceles(A,B,C) :- A==B, B=\=C.isosceles(A,B,C) :- B==C, B=\=A.escaleno(A,B,C) :- A=\=B, B=\=C, A=\=C.tipo_triangulo(A,B,C) :- equilatero(A,B,C), write(‘equilatero’).tipo_triangulo(A,B,C) :- isosceles(A,B,C), write(‘isosceles’).tipo_triangulo(A,B,C) :- escaleno(A,B,C), write(‘escaleno’).trianguloq(A,B,C) :- es_triangulo(A,B,C), tipo_triangulo(A,B,C).

� Planteamiento 2º

La solución anterior es efectiva, pero no capta la toda la información que disponemos sobre elproblema porque no se ha estructurado del todo bien. La solución propuesta enumeran todos loscasos posibles considerando las magnitudes a, b y c.La segunda restricción consiste en una enumeración de casos posibles disjuntos entre sí.Si realizamos una proyección de los símbolos a, b y c sobre la terna x, y y z, de tal forma quex<y<z, podemos simplificar dicha restricción. De paso podremos simplificar las demástambién.Condición previa para que T(x,y,z) sea triángulo:x>0 (puesto que x<y<z => y,z >0)Restricción necesaria para que T(x,y,z) sea triángulo:x+y>z (puesto que x,y<z)T(x,y,z) es equilátero six = z (puesto que x<y<z, si x=z => x=y=z)T(x,y,z) es isósceles si se cumplex=y, y!=zx!=y, y=zT(x,y,z) es escaleno si se cumplenx!=yy!=z si x!=y, y!=z => x!=z puesto que x<y<z

� Solución 3ª

ordena2(X,Y, X,Y) :- X=<Y.ordena2(X,Y, Y,X) :- X>Y.ordena3(A,B,C, X,Y,Z) :- ordena2(A, B, X1, Y1),ordena2(X1, C, X, Z1),ordena2(Y1, Z1, Y, Z).lados_positivos(X, _, _) :- X>0.lados_adecuados(X,Y,Z) :- X+Y>Z.es_triangulo(X,Y,Z):- lados_positivos(X,Y,Z), lados_adecuados(X,Y,Z).equilatero(X,Y,Z) :- X==Z.isosceles(X,Y,Z) :- X==Y, Y=\=Z.isosceles(X,Y,Z) :- X=\=Y, Y==Z.escaleno(X,Y,Z) :- X=\=Y, Y=\=Z.tipo_triangulo(X,Y,Z) :- equilatero(X,Y,Z), write(‘equilatero’).tipo_triangulo(X,Y,Z) :- isosceles(X,Y,Z), write(‘isosceles’).tipo_triangulo(X,Y,Z) :- escaleno(X,Y,Z), write(‘escaleno’).trianguloq(A,B,C):-ordena3(A,B,C,X,Y,Z), es_triangulo(X,Y,Z), tipo_triangulo(X,Y,Z).lados_positivos(X) :- X>0.

Page 29: Manual de Prolog

Introducción al lenguaje PROLOG 29

� Ejercicio 6

Enunciado:A).- Dado el siguiente árbol genealógico (ver figura 1), crear un base de hechos que lorepresente y el conjunto de cláusulas necesarias que me permitan establecer las relacioneshabituales en cualquier familia, como por ejemplo:

hermanos(X,Y). es hermano/a de Y ?padre(X,Y). X es padre de Y ?abuelos(X,Y). X es abuelo/a de Y ?primos(X,Y). X es primo/a de Y ?

También se diseñarán cláusulas que nos permitan relacionar diferentes familias, por ejemplo:� cuñados(X,Y). X es cuñado/a de Y ?

Se crearán cláusulas de carácter recursivo como:� antepasado(X,Y). X es antepasado/a de Y ?

B).- Se modificará el programa anterior, para permitir la inserción de nuevos hechos en nuestrabase. Como característica básica se considerará la inserción de este nuevo conocimiento:

“ Juan, cuyos padres son Pilar y Mario, decide casarse con Sara (sus padres no sonconocidos para nuestra base de hechos). Como efecto de este matrimonio tienen una hija a laque deciden ponerle el nombre de Sonia. “

Árbol Genealógico:

Familia 1 Familia 2

Antonio---Cándida José---MªAngeles

Juan---María Rosa---------------------------David Lucio---Pilar

José María----Antonio Luís Elena----Juan Antonio Alberto----Rosa Enrique

María Ana Pilar--------------Mario Rosa

Juan------Sara

Sonia

C).- En este apartado se pretende modelizar la Computación del Parentesco entre dospersonas de una familia, en primer lugar definiremos un conjunto de conceptos necesarios parapoder realizar el cálculo:

• Línea es el conjunto o serie de grados que pueden existir entre dos personas; puedeser recta o colateral.• Línea recta es la integrada por individuos que descienden unos de otros: padres,hijos, nietos,etc.• Línea colateral es la formada por personas que no descienden unas de otras perotienen ascendientes comunes: hermanos, tíos, primos, sobrinos, etc.

Page 30: Manual de Prolog

Introducción al lenguaje PROLOG 30

• GRADO es, en materia de parentesco, cada una de las generaciones existentes entredos personas relacionadas por vínculos de sangre. Así del padre al hijo hay unageneración o grado, entre abuelo y nieto existen dos grados.

Para calcular el grado existen dos sistemas diferentes:

� Derecho Civil: existen tantos grados como generaciones, así en la línea recta entre el nietoy el abuelo existen dos grados de parentesco. Si utilizamos la línea colateral, para calcularel grado de parentesco entre dos individuos, se asciende hasta el primer antepasado comúny luego se desciende hasta la persona respecto de la cual se computa el parentesco. La sumadel nº de generaciones de ambas ramas nos proporcionará el grado que existe entre losindividuos, por ejemplo, con este sistema el hermano se halla en segundo grado concualquier otro hermano, los primos hermanos distan cuatro grados, etc.

� Derecho Canónico: en el caso de la línea recta el cómputo es idéntico que en el caso delderecho civil. En la línea colateral se cuentan las generaciones o grados de la línea máslarga y no se suman como en el derecho civil. De esta forma, el hermano se encuentra enprimer grado con sus hermanos, y los primos hermanos se encontrarían en segundo grado.Esta computación rige solamente para el matrimonio canónico a efecto del impedimento deparentesco que ha de ser estimado conforme a ella.

Se pide construir un conjunto de reglas en Prolog que me permitan obtener los anterioresconceptos, por ejemplo:

� recta(X,Y,Z) :- nos dice si X tiene un parentesco directo con Y.� colateral(X,Y) :- nos dice si X tiene un parentesco colateral con Y� grado_civil(X,Y,Z) :- calcula el grado existente entre las personas X e Y aplicando

las leyes del derecho civil, Z estará instanciada al valor de ese grado.� grado_canonico(X,Y,Z) :- calcula el grado existente entre las personas X e Y

aplicando las leyes del derecho civil, Z estará instanciada al valor de ese grado.

Soluciones…Ejercicio 6

1. linea_recta(X,Y). linea_recta(X,Y) :- padre(X,Y). linea_recta(X,Y) :- padre(X,Z), linea_recta(Z,Y).

� Tiene el problema de que no es simétrica.� La circunstancia de que linea_recta(X,X) sea cierto es discutible a efectos de calcular el

grado de parentesco (sería un grado 0). 2. linea_recta(X,Y), simétrico.

antecesor(X,Y) :- padre(X,Y).antecesor(X,Y) :- padre(X,Z), antecesor(Z,Y).

linea_recta(X,Y) :- antecesor(X,Y).linea_recta(X,Y) :- antecesor(Y,X).

� hemos tenido que crear un nuevo predicado antecesor para evitar la recursividad infinita.

Page 31: Manual de Prolog

Introducción al lenguaje PROLOG 31

Apéndice.- SWI_Prolog

A continuación, se muestran un conjunto de predicados básicos para el manejo del intérpreteSWI-Prolog

Para una información más detallada, consultar la dirección Web:

http://grial.uc3m.es/~docweb/pl2/index.html

� Software y Manuales: http://grial.uc3m.es/~docweb/pl2/software.html

1.- Creación de un programa Prolog

El programa Prolog debe editarse en modo texto y contener la extensión “.pl”Ejemplo: program1.pl

2.- Cargar un programa

Una vez arrancado el intérprete Prolog , utilizaremos el predicado consult/1 Para cargar elconjunto de hechos y reglas que contiene el fichero. No debe utilizarse la extensión .pl

Si el fichero se ha leído correctamente por el intérprete, nos responderá algo similar a:

Una forma abreviada de cargar el programa puede realizarse utilizando los corchetes[program1].

Page 32: Manual de Prolog

Introducción al lenguaje PROLOG 32

3.- Efectuar preguntas simples

Para realizar preguntas simples al intérprete, podemos utilizar predicados simples que hayamospredefinido en el programa, dejando alguno de sus términos sin instanciar.

Ejemplo:?-p(a,X).?-saldo_cuenta(maria,Z).

4.- Ayuda online del intérprete

El intérprete SWI_Prolog nos proporciona una pequeña ayuda online sobre determinadospredicados, para ello pueden utilizarse las distintas versiones del predicado help.

� help Equivalente a utilizar (help/1).

� help(+What) muestra el predicado especificado del manual. Puede describirse mediante:

<Name>/<Arity> Muestra la ayuda existente del predicado. <Name> Muestra la ayuda existente de ese predicado con cualquier

aridad.<Section> Muestra la sección especificada, las secciones se identifican

por números separados por un guión: 2-3 (sección 2.3 delmanual).

Los números de una determinada sección pueden obtenerse utilizando apropos/1.

Ejemplos: ?- help(assert). /*muestra la información del predicado assert */ ?- help(3-4). /*muestra la información de la sección 3.4 */ ?- help('PL_retry'). /*muestra la ayuda de la función PL_retry() */

� apropos(+Pattern)Muestra todos los predicados, funciones y secciones que coinciden con el patrón de entrada (enminúsculas).Ejemplo:

?- apropos(file). /*muestra los predicados, funciones y secciones que contienen ‘file’ (o‘File’, etc) en su ayuda. */

� explain(+ToExplain)Obtenemos una explicación acerca de un determinado ‘objeto’ (cualquier tipo de datopermitido en Prolog).Ejemplo:?- explain(p)."p" is an atomuser:p/2 is a predicate defined in c:/david/docencia/carlos iii/pl2/prolog/ejemplo0.pl:5

Yes

Page 33: Manual de Prolog

Introducción al lenguaje PROLOG 33

5.- Salida del intérprete

halt/0 Termina la ejecución del intérprete Prolog, cerrando todos los ficheros abiertos.

halt(+Status) Termina la ejecución del intérprete con un determinado estado, el estado es un número entero.

6.- Entrada/Salida Estándar

A continuación, se muestran algunos predicados básicos para poder realizar operaciones deentrada/salida desde/sobre el terminal de salida de la computadora.

� current_op(?Precedence,?Type,?Name): Devuelve éxito cuando Name está definido comoun operador de tipo Type cuya precedencia es Precedence. (Otros predicados relacionadoscon este, op/3).

� display(+Term): Escribe el término Term sobre la salida estándar del dispositivo. Estepredicado suele emplearse normalmente para examinar la representación interna de untérmino.

� flush: Vuelca la salida de un programa sobre la salida estándar actual (verflush_output/1).

� get(-Char): Lee de la entrada actual caracteres y unifica Char con el próximo carácterintroducido (distinto al carácter blanco). Char se unifica con -1 si se trata del final de unfichero.

� get0(-Char): Lee de la entrada actual caracteres y unifica Char con el próximo carácterintroducido. Char se unifica con -1 si se trata del final de un fichero.

� nl: Escribe una línea en blando (carácter newline) sobre la salida estándar actual .

� op(+Precedence,+Type,+Name): Declara a Name como un operador de tipo Type con unaprecedencia Precedence.

� put(+Char): Escribe el carácter Char sobre la salida estándar del dispositivo.

� read(-Term): Lee un término desde la entrada estándar del dispositivo.

� skip(+Char): Lee y salta caracteres desde la entrada estándar hasta que encuentra elcarácter Char.

� tab(+Amount): Escribe un número dado (Amount) de espacios en blanco en la salidaestándar del dispositivo (Amount debe ser una expresión que pueda evaluarse como unentero positivo).

� write(+Term): Escribe el término Term sobre la salida estándar.

� writeq(+Term): Escribe el término Term sobre la salida estándar (sitúa el término entrecomillas). En este predicado, los términos pueden ser vueltos a leer con el predicadoread/1.

Page 34: Manual de Prolog

Introducción al lenguaje PROLOG 34

7.- Entrada/Salida desde Fichero

� close(+Stream): Cierra el fichero especificado por Stream.

� display(+Stream,+Term): Muestra un término Term que se encuentra en el ficheroespecificado por Stream.

� get(+Stream, -Char): Lee el siguiente carácter imprimible de un fichero y unifica sucorrespondiente valor ASCII con Char.

� get0(+Stream, -Char): Lee el siguiente carácter de un fichero y unifica su correspondientevalor ASCII con Char.

� nl(+Stream): Escribe una línea en blanco en el fichero especificado.

� open(+SrcDest,+Mode,?Stream): Apertura del fichero especificado por SrcDest(especifica un fichero Unix), el Mode puede ser de lectura (read), escritura (write) o pararealizar una ampliación del mismo (append). El término Stream puede ser una variable (seinstanciará a un entero que identifica mi fichero), o un átomo (en este caso se trata de unidentificador de fichero). En caso de no existir el fichero lo crea.

� put(+Stream,+Char): Escribe el carácter Char, en el fichero Stream.

� read(+Stream,-Term): Lee un término desde un fichero.

� see(+SrcDest): Abre un fichero para lectura y se sitúa al comienzo del mismo.

� seeing(?SrcDest): Unifica el nombre del fichero abierto actualmente con SrcDest .

� seen: Cierra el fichero actualmente abierto, y devuelve la entrada estándar del dispositivoal teclado del terminal.

� skip(+Stream,+Char): Lee y salta caracteres desde un fichero (Stream) hasta queencuentra el carácter Char.

� tab(+Stream,+Amount): Escribe un número dado (Amount) de espacios en blanco unfichero (Stream).

� tell(+SrcDest): Abre un fichero para escritura como si se tratase de la salida estándar.

� telling(?SrcDest): Devuelve el nombre de el fichero abierto por tell (unifica el nombre delactual fichero de salida con SrcDest).

� told: Cierra el fichero que se encuentre actualmente abierto, y devuelve la salida estándardel dispositivo a la pantalla del terminal.

� write(+Stream,+Term): Escribe el término Term sobre el fichero Stream.

� writeq(+Term): Escribe el término Term sobre el fichero Stream (los insertaentrecomillados).

Page 35: Manual de Prolog

Introducción al lenguaje PROLOG 35

8.- Funciones del Sistema

� [+Filespec��: Lee las cláusulas contenidas en el fichero especificado y las inserta en la basede datos (es una acción similar a ejecutar el predicado consult).

� chdir(+Path): Cambia el directorio de trabajo al directorio Path.

� consult(+File): Lee un fichero con formato Prolog (el fichero va sin extensión aunque pordefecto buscará el fichero File o File.pl, toma las cláusulas que encuentre en ese fichero ylas inserta en la base de datos

� delete_file(+File): Borra el fichero especificado.

� exists_file(+File): Produce éxito cuando el fichero especificado existe (esto no implicaque el usuario disponga de permiso de lectura o escritura sobre ese fichero).

� halt: Finaliza la ejecución del intérprete de Prolog o de la aplicación compilada.

� listing: Lista todos los predicados de la base de datos.

� listing(+Pred): Lista todos los predicados especificados por Pred.

� rename_file(+File1,+File2): Renombra File1 como File2.

� size_file(+File,-Size): Unifica la variable Size con el número de caracteres contenidos enFile.

� shell: Inicia un shell interactivo con Unix. El shell finaliza al teclear exit.

� shell(+Command): Ejecuta un comando de Unix.

� statistics: Muestra una tabla con información estadística acerca de la utilización delsistema.

Page 36: Manual de Prolog

Introducción al lenguaje PROLOG 36

9.- Funciones para la Depuración de Programas

� debug: Arranca el depurador (detendrá la ejecución de los programas en los puntosespías).

� debugging: Imprime el estado del depurador y los puntos espías sobre la salida actual.

� nodebug: Detiene el depurador (quita el modo traza y no se detiene en ningún puntoespía).

� nospy(+Pred): Borra el punto espía situado en el predicado especificado.

� nospyall: Borra todos los puntos espía del programa.

� notrace: Detiene el proceso de traza del programa.

� spy(+Pred): Sitúa un punto espía en el todos los predicados especificados por Pred.

� trace: Arranca el proceso de traza del programa.

� tracing: Devuelve éxito cuando el proceso de traza está activado.

Opciones de depuración:

+ : spy - : no spy/c|e|r|f|u|a} goal : find . : repeat finda : abort A : alternativesb : break c (return,space) : creepd : display goal e : exit from Prologf : fail [depth�� g : goalsh (?) : help i : ignorel : leap L : listingn : nodebug p : printr : retry s : skipu : up w : write goalC : toggle show context