Está en la página 1de 37

Introduccin al lenguaje PROLOG

NDICE

Bibliografa recomendada.

1.- Introduccin formal al lenguaje Prolog

2.- Clusulas

3.- Trminos

4.- Hechos

5.- Consultas

6.- Equiparacin

7.- Reglas

7.1.- Recursividad

7.2.- Recursividad encubierta

7.3.- Eficiencia

7.4.- Directivas para mejorar la eficiencia

10

8.- Desigualdad

11

9.- Operadores lgicos y aritmticos

11

10.- Igualdad y asignacin

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.- Negacin

17

15.- Progamacin Determinista/No Determinista

18

16.- Mecanismo de Resolucin

19

17.- Listas

20

18- Ejercicios Bsicos

23

Apndice.- SWI_Prolog

31

Introduccin al lenguaje PROLOG

BIBLIOGRAFA RECOMENDADA

Bibliografa Bsica

Prolog. Programming for artificial Intelligence


Ivan Bratko
Ed. Addison-Wesley, 1994
The Art of Prolog
L.Sterling, E.Shapiro
The MIT Press, Cambridge, Massachusetts,1994

Bibliografa Complementaria

Programming in Prolog
W.F.Clocksin, C.S.Mellish
Springer-Verlag,1987
Prolog. Introduccin a la Programacin de sistemas expertos
J.M.Orenga y Ortega, J.P.Snchez y Beltrn
Ed. RAMA, 1987

Introduccin al lenguaje PROLOG

1.- INTRODUCCIN FORMAL AL LENGUAJE PROLOG


PROLOG es un lenguaje declarativo e interpretado, en este tipo de lenguajes se representan los
conocimientos sobre un determinado dominio y sus relaciones. A partir de ese conocimiento, se
deducen 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 forma
simultnea las propiedades y sus interacciones.
Se declara el conocimiento disponible acerca de:

OBJETOS:
propiedades
relaciones

REGLAS, que determinan interacciones lgicas del tipo: si ocurre q, r, s y t


entonces P

Ventaja:
No hay que preocuparse de detalles de cmo resolver algo
Desventaja:
La resolucin no siempre es eficiente.

Desde un punto de vista lgico, un programa Prolog est constituido por un conjunto de
clusulas de Horn. Una clusula de Horn tiene la forma general:
p(t1,t2,.,tn) :- p1(.),p2(.),,pm(.)

con m >= 0

Donde tanto p como las pi son smbolos predicados con sus argumentos entre parntesis. A los
argumentos de un predicado se les denomina Trminos.
Las clusulas de Horn son expresiones condicionales, siendo el smbolo :- el condicional o
smbolo de la implicacin (normalmente en lgica se utiliza el smbolo
). As la clusula
anterior podra leerse de la siguiente forma:
SI p1(.) Y p2(.) Y Y pm(.) ENTONCES p(t1,t2,,tn)
o bien podra leerse tambin:
Es cierto p(t1,t2,,tn) SI es cierto p1(.) Y es cierto p2(.) Y Y es cierto
pm(.)
Cuando m=0, la clusula no tiene parte derecha, en este caso diremos que se trata de un hecho
o afirmacin.
p(t1,t2,,tn).
Cuando la clusula no tiene parte izquierda (o cabeza), se tiene una clusula negativa o
pregunta, este tipo de clusulas se utilizan para realizar la entrada/salida del programa:
?p1(.),p2(.),,pm(.)
Un trmino ti puede ser:

un tomo (nmero, constante)

Introduccin al lenguaje PROLOG

una variable
una estructura (functor): f(t1,t1,tm)
donde los argumentos ti son a su vez trminos

En la sintaxis estndar de Prolog (la que utilizaremos aqu se conoce como sintaxis de
Edimburgo), los smbolos de tomos (constantes), functores y predicados comienzan con una
letra minscula, los smbolos de variables comienzan con una letra mayscula o con un
subrayado.
Un ejemplo de un programa Prolog sera el siguiente:
1.
2.
3.
4.
5.

p(a,f(T,b)) :- q(Y,c,a),r(T,b).
p(a,b).
q(c,c,a).
q(a,b,c) :- r(g(a,b),d).
r(f(b,a),b).

Una computacin en Prolog es un proceso de RESOLUCION LINEAL CON UNIFICACIN


aplicado a una clusula negativa (la pregunta) y al conjunto de clusulas que constituyen el
programa. As la clusula negativa:
?p(a,X).
Tendra la siguiente interpretacin:
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 las
clusulas del programa?
Para resolver el objetivo ?p(a,X) aplicando resolucin lineal, se intenta su unificacin con la
parte izquierda de alguna clusula que contenga el mismo predicado/aridad. Si la unificacin es
posible, se sustituye el objetivo original por la lista de objetivos de la parte derecha de la
clusula utilizada en la unificacin (con las sustituciones de variables que la unificacin
implica). El proceso contina con el primer objetivo de la lista resultante hasta que
desaparezcan todos los objetivos. Si en un momento dado resulta imposible resolver un
objetivo, se retrocede (backtracking) al objetivo ms reciente con otras alternativas para su
resolucin, y se resuelve con la siguiente alternativa. Si no existen alternativas disponibles, el
objetivo de partida falla. Si se vaca la lista de objetivos, el objetivo queda resuelto.
El proceso desencadenado para el objetivo anterior sera el siguiente:
?p(a,X)
?q(Y,c,a),r(T,b)
?r(T,b)
?[ ]

resolviendo con 1, sustitucin X=f(T,b)


resolviendo con 3, sustitucin Y=c
resolviendo con 5, sustitucin T=f(a,b)
clusula vaca

Luego el objetivo original se ha resuelto (es cierto) con X=f(f(a,b),b), que es el resultado (o
salida) del clculo realizado por el programa Prolog.
La estrategia de resolucin descrita para aplicar el principio de resolucin y que suele utilizarse
en el Prolog estndar, se denomina primero_en_profundidad (depth first), pues el rbol de
bsqueda de la solucin se recorre en profundidad (se intenta resolver en primer lugar el
objetivo ms reciente de la lista de objetivos). El orden de utilizacin de las clusulas para
resolver un objetivo en Prolog standard es el determinado por su aparicin en el programa.
Nota: Existe alguna otra solucin a la resolucin de ese objetivo?

Introduccin al lenguaje PROLOG

2.- CLUSULAS
Un programa en Prolog est constituido por una secuencia de clusulas. Estas clusulas deben
representar todo el conocimiento necesario para resolver el problema.
Se pueden diferenciar tres tipos de Clusulas:
Hechos (afirmaciones), pueden representar:
Objetos
Propiedades de objetos.
Relaciones entre objetos.
Reglas.
Consultas (clusulas negativas).
Como se ha mencionado, un programa Prolog es una secuencia de clusulas, donde cada
clusula puede estar formada por uno o varios predicados. Las clusulas deben terminar
obligatoriamente en punto.

3.- TRMINOS
En Prolog hay tres tipos de trminos: CONSTANTES, VARIABLES Y ESTRUCTURAS
Tipo

Comentarios

Ejemplos

Casos Especiales

En Minsculas.

luis

Nombre de:

pedro

tomos especiales
:?-

Constante
tomo

Objetos

edad

Propiedades

color

Relaciones

padre
rey len

Nmero
Entero

Slo dgitos, +, -

63

Real

Y punto decimal

365.2425

Variable

Comienzan con Mayscula o


con _

Suma
_Y

Estructura

Trmino compuesto por otros


Trminos

edad(luis, 63)

padre_de(luis, eva)

Variable annima:
_

Introduccin al lenguaje PROLOG

4.- HECHOS
Es el mecanismo bsico para representar:
objetos/personas/conceptos.
propiedades de los objetos.
relaciones entre los objetos.
Ejemplos:
padre(luis).
padre_de(luis, pedro).
azul(cielo).
Una relacin viene definida por todas las instancias que aparecen con un predicado.
tipo de concepto

Ejemplo

aridad

objetos/personas/proposiciones

luis

predicado/0

pedro
cielo
Propiedades

padre

predicado/1

azul
Relaciones

padre_de

predicado/2, .../n

Los hechos pueden introducirse en la base de hechos del intrprete de Prolog mediante una
asercin:
?- 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).

Introduccin al lenguaje PROLOG

5.- CONSULTAS
Es el mecanismo para extraer conocimiento del programa:
?- amigos(pedro, antonio).
yes
?- amigos(pedro, eva).
no
?- amigos(pedro, pepe).
no

X = juan ;
X = vicente ;
no

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

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

?- amigos(antonio, pedro).
no

Ejemplo: Mi amigo, Vicente, busca amigos/as de mis amigos que sean millonarios/as y estn
solteros/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. El
intrprete de Prolog nos devuelve ms soluciones si utilizamos el punto y coma ; cuando
no existen ms soluciones que unifiquen con el objetivo, el intrprete contesta No.

6.- EQUIPARACIN
Este mecanismo permite comprobar si dos expresiones son equivalentes, produce como
resultado una sustitucin de trminos cuando esta es posible. Por ejemplo, si una variable est
libre y es equiparada con un valor numrico, se obtiene una instanciacin (asignacin) de la
variable 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 trminos T1 y T2 son equiparables:
T1, T2 son constantes => idnticas.
T1 o T2 es una variable => se equiparan instanciando el otro trmino a la variable.
T1, T2 son estructuras => los trminos que los componen son equiparables
manteniendo una instanciacin de las variables coherente.

Introduccin al lenguaje PROLOG

7 .- REGLAS
Permiten establecer relaciones ms elaboradas entre objetos, por ejemplo, relaciones
generalizadas o particularizadas, o relaciones causa-efecto. A continacin, se muestran un
conjunto 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 ms generales y flexibles, es necesario un mecanismo adicional. Para ello se
utilizar el concepto de recursividad.
Para definir el concepto antecesor_de puede definirse de una forma iterativa:
antecesor_de(X,Y) :- padre_de(X, Y).
antecesor_de(X,Y) :- padre_de(X, Z), padre_de(Z, Y).
antecesor_de(X,Y) :- padre_de(X, Z1),
padre_de(Z1, Z2),
padre_de(Z2, Y).
antecesor_de(X,Y) :- padre_de(X, Z1),
padre_de(Z1, Z2),
padre_de(Z2, Z3),
padre_de(Z3, Y).
...

% padre
% abuelo
% bisabuelo
% tatarabuelo

Este mecanismo no es eficiente, dado que no nos permite generalizar fcilmente el concepto de
antecesor. Prolog permite utilizar definiciones recursivas, que resuelven el problema de forma
elegante.
antecesor_de(X, Y) :- padre_de(X, Y).
antecesor_de(X, Y) :- padre_de(X, Z), antecesor(Z, Y).

Introduccin al lenguaje PROLOG

7.2.- Reglas. RECURSIVIDAD ENCUBIERTA


Uno de los peligros que conlleva la recursividad, es la de realizar definiciones circulares o que
el intrprete de Prolog no sea capaz de resolver.
El ejemplo ms simple de un caso problemtico sera:
antecesor_de(X, Y) :- antecesor_de(X, Y).
% que se puede reducir a la clusula: P => P
Esta clusula es declarativamente correcta, pero el intrprete de Prolog no podr resolverla
nunca y se quedar atrapado en un bucle infinito. De aqu se pueden observar otros casos
problemticos, por ejemplo si se define la siguiente base de hechos sobre las amistades de una
persona:
amigos(pedro, antonio).
amigos(pedro, flora).
...
amigos(fernando, pedro).
Si consideramos que el concepto amistad tiene una relacin conmutativa, entonces
posiblemente nos interesara definir la relacin de amistad inversa o complementaria:
amigos(X, Y) :- amigos(Y, X). % Peligro, recurrencia!
Esta definicin aparentemente lgica provoca un error. La forma correcta de definirlo sera a
travs de un nuevo predicado:
son_amigos(X, Y) :- amigos(X, Y).
son_amigos(X, Y) :- amigos(Y, X).

7.3.- Reglas. EFICIENCIA


En lgica matemtica no se impone un orden especial de las clusulas y de los trminos que
componen los programas. Sin embargo, en Prolog es necesario cuidar el orden de las clusulas
dentro de un programa, debido a que el intrprete unifica la reglas en el orden secuencial en el
que le han sido proprocionadas.
Volviendo a la definicin del predicado antecesor_de podemos ver que consta de dos clusulas,
una de las cuales posee dos metas (u objetivos). Esto permite generar cuatro definiciones
distintas de antecesor_de, permutando el orden de los trminos y de las clusulas.
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).

Introduccin al lenguaje PROLOG

10

En los ejemplos anteriores se obtienen resultados distintos.

antecesor1 es la ms eficiente y funciona siempre.


antecesor2 es menos eficiente.
antecesor3 slo funciona para algunos casos.
antecesor4 no funciona nunca, siempre se queda atrapado en un bucle infinito.

Ejemplos:
?- antecesor3(antonio, carlos).
% Verifica que la relacin es cierta.
?- antecesor3(carlos, maria).
% La relacin 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 ejecucin de nuestro
programa Prolog sea lo ms eficiente posible.

Primero los objetivos ms sencillos

- Ordenacin de clusulas:
1
las ms especficas.
2
las ms generales (con recursividad).
Ejemplo:
antecesor(X, Y) :- padre_de(X,Y).
antecesor(X, Y) :- padre_de(X,Y), antecesor(Z,Y).

- Ordenacin de trminos dentro de una clusula:


1
los trminos ms especficos.
2
los trminos ms generales (recursivos).
Ejemplo:
antecesor(X, Y) :- padre_de(X,Y),
antecesor(Z,Y).

Acotar el espacio de bsqueda

amigos_interesantes(X, Z) :- % Z = X!
amigos(Y, X), amigos(Y, Z), millonario(Z), soltero(Z).
Sabiendo que los amigos son ms frecuentes que los millonarios y solteros, resultar ms
eficiente a la hora de realizar la bsqueda cambiar el orden de las metas:
amigos_interesantes(X, Z) :- % Z = X!
millonario(Z), soltero(Z), amigos(Y, X), amigos(Y, Z).

Introduccin al lenguaje PROLOG

11

8.- DESIGUALDAD
Para comprobar si dos trminos son distintos, disponemos de diferentes operadores.
Desigualdad \==
Comprueba si dos trminos son distintos. Por ejemplo, si dos variables tienen distintos valores
instanciados.
Desigualdad aritmtica
=\=
Verifica la desigualdad numrica 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 comparacin aritmtica son:
< ; > ; =< ; >=
Operadores y funciones aritmticas vlidas en Prolog son:
+
/
//
mod
abs
**

*
divisin real.
divisin entera.
resto de divisin entera.
valor absoluto.
potencia.

^
potencia.
max valor mximo de dos.
min
valor mnimo de dos.
round redondea al entero ms prximo.
integer trunca a la parte entera.
float convierte en un valor real.

Introduccin al lenguaje PROLOG

12

10.- IGUALDAD Y ASIGNACION


Disponemos de cuatro tipos de operadores de igualdad:
Igualdad aritmtica

[=:=]. Comprueba la igualdad numrica de las expresiones argumento.

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

[==]. Comprueba si los trminos argumento son idnticos.

igual2(X, Y) :- X == Y.
Unificacin [ = ]. Comprueba si los trminos argumento son unificables (equiparables). Es
equivalente a la asignacin directa entre variables en un lenguaje procedimental. Da fallo si la
unificacin no es posible.
igual3(X, Y) :- X = Y.
Una definicin equivalente sera:
igual4(X,X).
Asignacin

[is]. Evala la segunda expresin e intenta asignar el valor obtenido a la

variable. No es conmutativo!
incremento(X,Y) :- Y is X+1.
Una definicin similar a la de igualdad sera:
igual5(X, Y) :- X is Y.
Los operadores antes mencionados, aunque parten de conceptos muy distintos, poseen
comportamientos similares, lo cul puede inducir a errores. A continuacin se muestra una
tabla comparativa de todas las posibilidades existentes.
Operador
Ejemplo
Igual?(3,3).
Igual?(1,3).
Igual?(1+2,3).
Igual?(3,1+2).
Igual?(X,1+2).
Igual?(1+2,X).
Igual?(3,X).
Igual?(X,3).
Igual?(hola,hola).
Igual?(1.0,1).
Igual?(1,1.0).
Igual?(1.0,1.0).
Igual?(1.1,1.1).
*
**

=:=
igual1
yes
no
yes
yes
*
*
*
*
**
yes
yes
yes
yes

==
igual2
yes
no
no
no
no
no
no
no
yes
no
no
yes
yes

Excepcin: Variable X libre.


Error: hola no es funcin (o expresin) vlida.

=
igual3
yes
no
no
no
X=1+2
X=1+2
X=3
X=3
yes
no
no
yes
yes

=
igual4
yes
no
no
no
X=1+2
X=1+2
X=3
X=3
yes
no
no
yes
yes

is
igual5
yes
no
no
yes
X=3
*
*
X=3
yes
no***
yes***
no***
yes***

Introduccin al lenguaje PROLOG

***

13

Prolog tiene tendencia a convertir valores reales a enteros. En el segundo argumento


del operador is detecta que se puede convertir en entero.

Introduccin al lenguaje PROLOG

14

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 ms comunes son:

Trminos (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)
igual1(vlibre, constante)
igual1(constante, vlibre)
igual1(vlibre, vlibre)

funciona
no funciona
no funciona
no funciona

==> igual1(+, +)

Resumen : igual1(+,+).

igual4(X,X).
igual4(constante, constante)
igual4(vlibre, constante)
igual4(constante, vlibre)
igual4(vlibre, vlibre)

funciona
funciona
funciona
funciona

==> igual4(+, +)
==> igual4(-, +)
==> igual4(+, -)
==> igual4(-, -)

Resumen : igual4(?, ?)

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

funciona
funciona
no funciona
no funciona

==> igual5(+, +)
==> igual5(-, +)

Resumen : igual5(?,+).

Se puede incluir ms informacin sobre el tipo concreto de argumento, por ejemplo: nmero,
expresin, carcter,...
igual1(X, Y) :- X =:= Y.
Resumen : igual1(+,+).
Los argumentos deben ser expresiones numricas:
==>

igual1(+expresin,+expresin).

igual4(X,X).
Resumen : igual4(?, ?)
Los argumentos pueden ser cualquier tipo de trmino:
==>

igual4(?trmino,?trmino).

igual5(X, Y) :- X is Y.
Resumen : igual5(?,+).
El primer argumento pueden ser una variable libre o constante numrica, el segundo debe ser
una expresin numrica:
==>
igual5(?nmero,+expresin).
Es conveniente incluir informacin de este tipo en los programas cada vez que se define un
predicado.

Introduccin al lenguaje PROLOG

15

12.- EFICIENCIA Y CORTE


Supongamos que se desea programar en Prolog la siguiente funcin matemtica:

Funcin escaln

4
2
0

-6

-3

0,

f ( x) = 2,
4,

x<3
3 x<6
6 x

Una posible solucin (la ms intuitiva) sera la mostrada a continuacin:


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 equiparacin:
f(X,0) :- X < 3.
f(X,2) :- 3 =< X, X < 6.
f(X,4) :- 6 =< X.

% f(+,?)

Si analizamos el problema, resulta que las soluciones mostradas son poco eficientes debido a
que se hacen demasiadas comprobaciones. Por ejemplo, al intentar calcular ?-f(2,Y),Y =:= 2.
Se comprueban las 3 clusulas cuando slo hara falta comprobar una.

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

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

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


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

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

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


fallo!

fallo!

Introduccin al lenguaje PROLOG

16

12.1.- CORTE VERDE


Existe un predicado que capaz de cortocircuitar la bsqueda una vez que es evaluado: el
corte, representado con el smbolo de admiracin !.El corte, es un predicado que siempre se
evala como cierto y que impide que se continen evaluando el resto de reglas.
f(X,0) :- X < 3, !.
f(X,2) :- 3 =< X, X < 6, !.
f(X,4) :- 6 =< X.

% f(+,?)

Basndonos en un programa semnticamente correcto hemos aadido el operador de corte para


obtener un programa ms eficiente. => Corte Verde.
Esto quiere decir que si eliminamos el predicado de corte, el programa funcionar tambin,
pero tendr el defecto de carecer de una interpretacin lgica o declarativa. Es necesario una
interpretacin procedimental para entender este predicado.

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

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

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

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


fallo!

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


fallo!

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 corte
las hace superfluas. En el ejemplo, la segunda clusula slo se alcanza cuando X>3 y la tercera
cuando 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) dara cierto. Qu se
ha hecho mal?. El problema es que el nuevo programa se basa en un programa semnticamente
incorrecto, si eliminsemos el corte, observaramos que al eliminar el operador de corte
obtenemos un programa incorrecto:
f(X,0) :- X < 3.
f(X,2) :- X < 6.

% MAL!

Introduccin al lenguaje PROLOG

17

f(X,4).
Este tipo de corte (Corte Rojo) debe emplearse con sumo cuidado!
Partiendo del ejemplo anterior:
f(X,0) :- X < 3, !.
f(X,2) :- X < 6, !.
f(X,4).

% f(+,-)

El motivo de perder el modo f(+,+) es debido a una interaccin poco obvia entre la
equiparacin, las condiciones y el corte. El programa realmente debera ser:
f(X,Y) :- X < 3, !, Y is 0.
f(X,Y) :- X < 6, !, Y is 2.
f(X,Y) :- Y is 4.

% f(+,?)

No obstante este programa sigue basndose en un programa semnticamente incorrecto; al


eliminar nuevamente el operador de corte se sigue obteniendo un programa incorrecto:
f(X,Y) :- X < 3, Y is 0.
f(X,Y) :- X < 6, Y is 2.
f(X,Y) :- Y is 4.

% MAL!

?- f(2, X).
X=0;
X=2;
X=4
Supongamos que se desea programar otra funcin matemtica en Prolog::
Funcin rampa
6
5
4
3
2
1
0
-3

-2

-1

-1

10

-2

a
Una primera solucin, sin utilizar el corte podra 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 obtendra:
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.

3 x ,

g ( x ) = x 3,

9 x ,

x<3
3 x < 6
6 x

Introduccin al lenguaje PROLOG

18

Si se trazan algunos ejemplos sencillos se pueden observar los posibles casos que pueden
presentarse con esta solucin:
1 se evala la primera clusula, por ejemplo para g(4,Z). El primer trmino es falso: X<3.
El intrprete pasa a verificar la segunda clusula.
2 El primer trmino es cierto y se aplica el corte, pero el ltimo trmino es falso. Por ejemplo,
en g(2,3). El intrprete retrocede con falso; debido al corte no se intenta verificar otra
clusula. El intrprete responde: No.
3 El primer trmino es cierto y se aplica el corte, el ltimo trmino es cierto o equiparable. Por
ejemplo, en g(2,1) o g(2, Z). El intrprete retrocede con cierto; debido al corte no se intenta
verificar otra clusula. El intrprete responde: S.

13.- FALLO
fail (fallo) es un predicado que siempre produce fallo. Es til cuando queremos detectar casos
explcitos que invalidan un predicado.
Ejemplo: Programa que simule una puerta lgica nand de 7 entradas (equivale a not and).
Esta puerta lgica slo da falso en su salida cuando todas las entradas son ciertas (en este caso
vamos a suponer que entrada=1 equivale a cierto).
nand7(0, _, _, _, _, _, _).
nand7(_, 0, _, _, _, _, _).
nand7(_, _, 0, _, _, _, _).
nand7(_, _, _, 0, _, _, _).
nand7(_, _, _, _, 0, _, _).
nand7(_, _, _, _, _, 0, _).
nand7(_, _, _, _, _,_, _0).
La solucin queda ms sencilla si se utiliza el fallo:
nand7(1, 1, 1, 1, 1, 1, 1) :- !, fail.
nand7(_, _, _, _, _, _, _).
Nota: fail suele utilizarse en combinacin con el corte.

14.- NEGACIN
Existe un predicado de negacin en Prolog (not) que est implementado como negacin por
fallo, esto quiere decir que se evala como falso cualquier cosa que Prolog sea incapaz de
verificar 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.

Introduccin al lenguaje PROLOG

19

pobre(X) :- not millonario(X).


?- 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 definan una serie de situaciones que podan darse,
y qu haba que hacer en cada caso (programa determinista).
Ejemplo: programa para calcular el mnimo de dos nmeros:
min(X,Y, Z) :- X < Y, Z is X.
min(X,Y, Z) :- X >= Y, Z is Y.

% min(+,+,?)

Ejemplo: dados tres hechos que describen los lados de un tringulo, escribir un programa que
devuelva 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 forma
combinatoria soluciones posibles y comprobar si son correctas. El mtodo de bsqueda de
Prolog se encarga de retroceder cuando una solucin no es vlida.
ordena3 (X, Y, Z) :- lado(Xn, X), lado(Yn, Y), lado(Zn, Z),
Xn \= Yn, Xn \= Zn, Yn \= Zn, X =< Y, Y =< Z.

Introduccin al lenguaje PROLOG

20

16.- MECANISMO DE RESOLUCION


Como se explic en la introduccin, Prolog utiliza un mecanismo conocido como Resolucin
lineal con unificacin para resolver las preguntas que se le plantean (clusulas negativas), el
mecanismo consiste en realizar una bsqueda en profundidad y retroceso (backtracking)
tratando de unificar la clusula objetivo con las contenidas en la base de hechos, hasta lograr
alcanzar la clusula vaca. A continuacin, se muestra de forma simplificada el algoritmo
utilizado:
1.
2.
3.
4.

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


metas.
Se realiza una llamada recursiva al procedimiento de bsqueda con la lista de
metas pendientes.
Si se encuentra solucin, imprimirla
Si no hay solucin, imprimir false.

PROCEDIMIENTO DE BSQUEDA:
1
Se extrae la primera meta eliminndola 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 vaca llamar al procedimiento de bsqueda de forma
recursiva con ListaMetas y las variables equiparadas.
6
Si ListaMetas est vaca provocar un retorno con las metas satisfechas y las
variables equiparadas.
7
Si hay solucin 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 solucin alguna, provocar un retroceso, e.d. un retorno
sin solucin.
Ejemplo. Base de hechos:
primoroso(zorro).
primoroso(oso).
amoroso(oso).
astuto(zorro).

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

Mecanismo de resolucin:
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)

Introduccin al lenguaje PROLOG

21

PMeta = primera (ListaMetas) = amoroso(X), X = zorro.


ListaMetas = resto (ListaMetas) = { }
Mientras sea posible:
Primer hecho: amoroso(oso) satisface PMeta?, no;
Retroceso sin solucin 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 Solucin { X = oso }
Provocar retorno con Solucin { X = oso }
Imprimir Solucin X = oso.

17.- LISTAS
Una lista es una secuencia ordenada de elementos que pueden tener cualquier longitud. Los
elementos de una lista puede ser cualquier tipo de trminos (constantes, variables o
estructuras), o incluso otra lista. Las listas en Prolog pueden representarse como un caso
particular de rbol, una lista est formada por dos elementos: la cabeza (primer elemento de la
lista) y la cola (resto de elementos de la lista). Ambos elementos se consideran componentes de
la estructura cuyo functor es el punto .
Ejemplos:
1. Lista con un nico elemento a
Notacin en Prolog .(a,[ ])
Representacin grfica

.
a

[ ] %lista vaca

2. Lista con tres tomos a,b,c


Notacin en Prolog .(a,.(b,.(c,[])))
Representacin grfica
a

.
.
b

.
c

[ ] %lista vaca

Debido al frecuente uso de este tipo de estructura, Prolog permite una notacin abreviada
para representar listas. Los elementos de la lista aparecen separados por comas, y la lista
completa aparece entre corchetes.

[a, b, c]
[]

Lista con los tres elementos a, b y c


Lista vaca.

En la definicin de predicados se pueden usar adems variables y un separador:


[a | L]

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

Introduccin al lenguaje PROLOG

22

[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 la


variable L (cola).

[X, Y | L]

Lista con el primer elemento instanciado en la variable X, el segundo en Y y el


resto en la variable L (cola).

Ejemplos de predicados tiles en el manejo de listas.

1.- Nmero 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 forma
pertenece(X, [ ]) :- fail.
pertenece(X, [X|L]).
pertenece(X, [Y|L]) :- X\=Y, pertenece(X, L).
% 2 forma
pertenece(X, [X|L]).
pertenece(X, [Y|L]) :- pertenece(X, L).

3.- Creacin 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.- Eliminacin de un elemento X de una lista L1, como consecuencia se obtiene la lista L2 (se
elimina la primera aparicin del elemento).
elimina(X,L1,L2)
% 1 forma
elimina(X,[]) :- fail.
elimina(X,[X|Cola],Cola).
elimina(X,[Y|C1],[Y|C2]) :- elimina(X,C1,C2).
% 2 forma
elimina(X,[X|Cola],Cola).
elimina(X,[Y|C1],[Y|C2]) :- elimina(X,C1,C2).

Introduccin al lenguaje PROLOG

23

5.- Eliminacin de todas las apariciones de un elemento X en una lista L1, como consecuencia
se 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 unificacin de listas.

Lista 1
[X,Y,Z]
[mustang]
[X,Y|Z]

Lista 2
[esto,es,prolog]
[X|Y]
[cuando,harry,encontro,a,sally]

[X,busca,Z]
[X,[actor,Z]]
[[el,Y]|Z]

[harry,Y,sally]
[cine,[Y,meg]]
[[X,libro],esta,aqu]

Instanciaciones
X=esto, Y=es, Z=prolog
X=mustang, Y=[]
X=cuando, Y=harry,
Z=[encontro,a,sally]
X=harry, Y=busca, Z=sally
X=cine, Y=actor, Z=meg
X=el, Y=libro, Z=[esta,aqu]

Si se tienen dudas de la posible unificacin de dos listas o de trminos en general, se puede


asegurar el resultado de la unificacin utilizando el predicado interno = del intrprete de
Prolog.
Ejemplos:
?-[X,libro]=[lapiz,Y].
X=lapiz
Y=libro
Yes
?-[X,libro]=[Y,lapiz].
No

Introduccin al lenguaje PROLOG

24

18.- EJERCICIOS BSICOS

Ejercicio 1

Enunciado: Programar en Prolog una clusula que calcule el factorial de n.

SolucionesEjercicio 1

Solucin 1

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

La solucin anterior no funciona bien si le pasamos un nmero negativo, para evitar este
problema podemos utilizar el fallo y el corte:

Solucin 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.

Solucin 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.

Solucin 4

factorial4(N, _) :- N < 0, !, fail.


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

Introduccin al lenguaje PROLOG

25

Ejercicio 2

Enunciado: Programar la siguiente funcin matemtica en Prolog.


Funcin Sierra
8
7
6
5
4
3
2
1
0
-1
-2
-3

12

nodefinida x < 0
x,
0 x<3

h( x) = x 3, 3 x < 6
x 6, 6 x < 9

nodefinida x 9

SolucionesEjercicio 2

Solucin 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 solucin se emplea el predicado de corte y el de fallo para mejorar la eficiencia.

Solucin 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).

Solucin 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.

Solucin 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).

Introduccin al lenguaje PROLOG

26

Ejercicio 3

Enunciado: Programacin determinista/no determinista del ejemplo visto en el apartado 15.

SolucionesEjercicio 3

Solucin no determinista (ms eficiente)

ordena3 (X, Y, Z) :- lado(Xn, X), lado(Yn, Y),


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

Solucin 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).

Solucin 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.

Introduccin al lenguaje PROLOG

27

Ejercicio 4

Enunciado: Implementar la estructura de hechos en Prolog que nos permita trabajar y


representar datos estructurados. Para ello, se pide obtener una representacin vlida para un
tringulo, donde podremos representar las tres coordenadas de los puntos que lo forman.

SolucionesEjercicio 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 si
es posible construir un tringulo cuyos lados tengan longitud a, b y c.
De ser as, deber indicar tambin el tipo de tringulo: escaleno, issceles o equiltero.
La caberecera que se definira en Pascal sera:
FUNCTION TrianguloQ (X, Y, Z : REAL) : BOOLEAN ;
...
Escribir un programa equivalente en Prolog.
trianguloq(A,B,C) ...

SolucionesEjercicio 5

Solucin en PASCAL
FUNCTION TrianguloQ (X, Y, Z : REAL) : BOOLEAN ;
PROCEDURE Ordena3 (VAR X, Y, Z : REAL) ;
PROCEDURE Swap2 (VAR V1, V2 : REAL) ;
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;

(* Ordena2 *)

BEGIN
Ordena3 (X, Y, Z);
IF (X > 0) AND (X + Y > Z) THEN
BEGIN
IF (X = Z) THEN

(* Es_triangulo *)

Introduccin al lenguaje PROLOG

28
WRITELN (Equilatero);
ELSE IF (X = Y) OR (Y = Z)
WRITELN (Issceles);
ELSE
WRITELN (Escaleno);
RETURN (TRUE);

END
ELSE RETURN (FALSE);
END;

Planteamiento 1

En primer lugar, se plantean las condiciones necesarias para poder construir un tringulo
T(a,b,c) a partir de las magnitudes a, b y c.
Condiciones previas para que T(a,b,c) sea tringulo: [a>0, b>0, c>0]
Restriccin necesaria para que T(a,b,c) sea tringulo:
a+b>c
si
c>a,b
a+c>b
si
b>a,c
b+c>a
si
a>b,c

T(a,b,c) es equiltero si
a=b=c
T(a,b,c) es issceles si se cumple
a=c, b!=a
a=b, c!=a
c=b, a!=c
T(a,b,c) es escaleno si se cumplen
a!=b
b!=c
a!=c

Solucin 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).

Solucin 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.

Introduccin al lenguaje PROLOG

29

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 solucin anterior es efectiva, pero no capta la toda la informacin que disponemos sobre el
problema porque no se ha estructurado del todo bien. La solucin propuesta enumeran todos los
casos posibles considerando las magnitudes a, b y c.
La segunda restriccin consiste en una enumeracin de casos posibles disjuntos entre s.
Si realizamos una proyeccin de los smbolos a, b y c sobre la terna x, y y z, de tal forma que
x<y<z, podemos simplificar dicha restriccin. De paso podremos simplificar las dems
tambin.
Condicin previa para que T(x,y,z) sea tringulo:
x>0
(puesto que x<y<z => y,z >0)
Restriccin necesaria para que T(x,y,z) sea tringulo:
x+y>z
(puesto que x,y<z)
T(x,y,z) es equiltero si
x=z
(puesto que x<y<z, si x=z => x=y=z)
T(x,y,z) es issceles si se cumple
x=y, y!=z
x!=y, y=z
T(x,y,z) es escaleno si se cumplen
x!=y
y!=z
si x!=y, y!=z => x!=z puesto que x<y<z

Solucin 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.

Introduccin al lenguaje PROLOG

30

Ejercicio 6

Enunciado:
A).- Dado el siguiente rbol genealgico (ver figura 1), crear un base de hechos que lo
represente y el conjunto de clusulas necesarias que me permitan establecer las relaciones
habituales en cualquier familia, como por ejemplo:
hermanos(X,Y).
padre(X,Y).
abuelos(X,Y).
primos(X,Y).

es hermano/a de Y ?
X es padre de Y ?
X es abuelo/a de Y ?
X es primo/a de Y ?

Tambin se disearn clusulas que nos permitan relacionar diferentes familias, por ejemplo:
cuados(X,Y).
X es cuado/a de Y ?
Se crearn clusulas de carcter recursivo como:
antepasado(X,Y). X es antepasado/a de Y ?
B).- Se modificar el programa anterior, para permitir la insercin de nuevos hechos en nuestra
base. Como caracterstica bsica se considerar la insercin de este nuevo conocimiento:
Juan, cuyos padres son Pilar y Mario, decide casarse con Sara (sus padres no son
conocidos para nuestra base de hechos). Como efecto de este matrimonio tienen una hija a la
que deciden ponerle el nombre de Sonia.
rbol Genealgico:
Familia 1

Familia 2

Antonio---Cndida
Juan---Mara
Jos

Rosa---------------------------David

Mara----Antonio Lus
Mara

Jos---MAngeles
Lucio---Pilar

Elena----Juan Antonio Alberto----Rosa


Ana

Pilar--------------Mario

Enrique

Rosa

Juan------Sara
Sonia
C).- En este apartado se pretende modelizar la Computacin del Parentesco entre dos
personas de una familia, en primer lugar definiremos un conjunto de conceptos necesarios para
poder realizar el clculo:
Lnea es el conjunto o serie de grados que pueden existir entre dos personas; puede
ser recta o colateral.
Lnea recta es la integrada por individuos que descienden unos de otros: padres,
hijos, nietos,etc.
Lnea colateral es la formada por personas que no descienden unas de otras pero
tienen ascendientes comunes: hermanos, tos, primos, sobrinos, etc.

Introduccin al lenguaje PROLOG

31

GRADO es, en materia de parentesco, cada una de las generaciones existentes entre
dos personas relacionadas por vnculos de sangre. As del padre al hijo hay una
generacin 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 lnea recta entre el nieto
y el abuelo existen dos grados de parentesco. Si utilizamos la lnea colateral, para calcular
el grado de parentesco entre dos individuos, se asciende hasta el primer antepasado comn
y luego se desciende hasta la persona respecto de la cual se computa el parentesco. La suma
del n de generaciones de ambas ramas nos proporcionar el grado que existe entre los
individuos, por ejemplo, con este sistema el hermano se halla en segundo grado con
cualquier otro hermano, los primos hermanos distan cuatro grados, etc.
Derecho Cannico: en el caso de la lnea recta el cmputo es idntico que en el caso del
derecho civil. En la lnea colateral se cuentan las generaciones o grados de la lnea ms
larga y no se suman como en el derecho civil. De esta forma, el hermano se encuentra en
primer grado con sus hermanos, y los primos hermanos se encontraran en segundo grado.
Esta computacin rige solamente para el matrimonio cannico a efecto del impedimento de
parentesco que ha de ser estimado conforme a ella.

Se pide construir un conjunto de reglas en Prolog que me permitan obtener los anteriores
conceptos, 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.

SolucionesEjercicio 6
1. linea_recta(X,Y).
linea_recta(X,Y) :linea_recta(X,Y) :-

padre(X,Y).
padre(X,Z),

linea_recta(Z,Y).

Tiene el problema de que no es simtrica.


La circunstancia de que linea_recta(X,X) sea cierto es discutible a efectos de calcular el
grado de parentesco (sera un grado 0).
2. linea_recta(X,Y), simtrico.
antecesor(X,Y) :antecesor(X,Y) :-

padre(X,Y).
padre(X,Z),

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

antecesor(X,Y).
antecesor(Y,X).

antecesor(Z,Y).

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

Introduccin al lenguaje PROLOG

32

Apndice.- SWI_Prolog
A continuacin, se muestran un conjunto de predicados bsicos para el manejo del intrprete
SWI-Prolog
Para una informacin ms detallada, consultar la direccin Web:

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

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

1.- Creacin de un programa Prolog


El programa Prolog debe editarse en modo texto y contener la extensin .pl
Ejemplo:
program1.pl

2.- Cargar un programa


Una vez arrancado el intrprete Prolog , utilizaremos el predicado consult/1 Para cargar el
conjunto de hechos y reglas que contiene el fichero. No debe utilizarse la extensin .pl

Si el fichero se ha ledo correctamente por el intrprete, nos responder algo similar a:

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

Introduccin al lenguaje PROLOG

33

3.- Efectuar preguntas simples


Para realizar preguntas simples al intrprete, podemos utilizar predicados simples que hayamos
predefinido en el programa, dejando alguno de sus trminos sin instanciar.
Ejemplo:
?-p(a,X).
?-saldo_cuenta(maria,Z).

4.- Ayuda online del intrprete


El intrprete SWI_Prolog nos proporciona una pequea ayuda online sobre determinados
predicados, 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 seccin especificada, las secciones se identifican
por nmeros separados por un guin: 2-3 (seccin 2.3 del
manual).
Los nmeros de una determinada seccin pueden obtenerse utilizando apropos/1.

Ejemplos:
?- help(assert). /*muestra la informacin del predicado assert */
?- help(3-4).
/*muestra la informacin de la seccin 3.4 */
?- help('PL_retry'). /*muestra la ayuda de la funcin PL_retry() */
apropos(+Pattern)
Muestra todos los predicados, funciones y secciones que coinciden con el patrn de entrada (en
minsculas).
Ejemplo:
?- apropos(file). /*muestra los predicados, funciones y secciones que contienen file (o
File, etc) en su ayuda. */
explain(+ToExplain)
Obtenemos una explicacin acerca de un determinado objeto (cualquier tipo de dato
permitido en Prolog).
Ejemplo:
?- explain(p).
"p" is an atom
user:p/2 is a predicate defined in
c:/david/docencia/carlos iii/pl2/prolog/ejemplo0.pl:5
Yes

Introduccin al lenguaje PROLOG

34

5.- Salida del intrprete


halt/0
Termina la ejecucin del intrprete Prolog, cerrando todos los ficheros abiertos.
halt(+Status)
Termina la ejecucin del intrprete con un determinado estado, el estado es un nmero entero.

6.- Entrada/Salida Estndar


A continuacin, se muestran algunos predicados bsicos para poder realizar operaciones de
entrada/salida desde/sobre el terminal de salida de la computadora.

current_op(?Precedence,?Type,?Name): Devuelve xito cuando Name est definido como


un operador de tipo Type cuya precedencia es Precedence. (Otros predicados relacionados
con este, op/3).

display(+Term): Escribe el trmino Term sobre la salida estndar del dispositivo. Este
predicado suele emplearse normalmente para examinar la representacin interna de un
trmino.

flush:
Vuelca la salida de un programa sobre la salida estndar actual (ver
flush_output/1).

get(-Char): Lee de la entrada actual caracteres y unifica Char con el prximo carcter
introducido (distinto al carcter blanco). Char se unifica con -1 si se trata del final de un
fichero.

get0(-Char): Lee de la entrada actual caracteres y unifica Char con el prximo carcter
introducido. Char se unifica con -1 si se trata del final de un fichero.

nl: Escribe una lnea en blando (carcter newline) sobre la salida estndar actual .

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


precedencia Precedence.

put(+Char): Escribe el carcter Char sobre la salida estndar del dispositivo.

read(-Term): Lee un trmino desde la entrada estndar del dispositivo.

skip(+Char): Lee y salta caracteres desde la entrada estndar hasta que encuentra el
carcter Char.

tab(+Amount): Escribe un nmero dado (Amount) de espacios en blanco en la salida


estndar del dispositivo (Amount debe ser una expresin que pueda evaluarse como un
entero positivo).

write(+Term): Escribe el trmino Term sobre la salida estndar.

writeq(+Term): Escribe el trmino Term sobre la salida estndar (sita el trmino entre
comillas). En este predicado, los trminos pueden ser vueltos a leer con el predicado
read/1.

Introduccin al lenguaje PROLOG

35

7.- Entrada/Salida desde Fichero

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

display(+Stream,+Term): Muestra un trmino Term que se encuentra en el fichero


especificado por Stream.

get(+Stream, -Char): Lee el siguiente carcter imprimible de un fichero y unifica su


correspondiente valor ASCII con Char.

get0(+Stream, -Char): Lee el siguiente carcter de un fichero y unifica su correspondiente


valor ASCII con Char.

nl(+Stream): Escribe una lnea 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 para
realizar una ampliacin del mismo (append). El trmino Stream puede ser una variable (se
instanciar a un entero que identifica mi fichero), o un tomo (en este caso se trata de un
identificador de fichero). En caso de no existir el fichero lo crea.

put(+Stream,+Char): Escribe el carcter Char, en el fichero Stream.

read(+Stream,-Term): Lee un trmino desde un fichero.

see(+SrcDest): Abre un fichero para lectura y se sita 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 estndar del dispositivo
al teclado del terminal.

skip(+Stream,+Char): Lee y salta caracteres desde un fichero (Stream) hasta que


encuentra el carcter Char.

tab(+Stream,+Amount): Escribe un nmero dado (Amount) de espacios en blanco un


fichero (Stream).

tell(+SrcDest): Abre un fichero para escritura como si se tratase de la salida estndar.

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

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

write(+Stream,+Term): Escribe el trmino Term sobre el fichero Stream.

writeq(+Term): Escribe el trmino Term sobre el fichero Stream (los inserta


entrecomillados).

Introduccin al lenguaje PROLOG

36

8.- Funciones del Sistema

[+Filespec]]: Lee las clusulas contenidas en el fichero especificado y las inserta en la base
de datos (es una accin 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 extensin aunque por
defecto buscar el fichero File o File.pl, toma las clusulas que encuentre en ese fichero y
las 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 implica


que el usuario disponga de permiso de lectura o escritura sobre ese fichero).

halt: Finaliza la ejecucin del intrprete de Prolog o de la aplicacin 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 nmero de caracteres contenidos en


File.

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 informacin estadstica acerca de la utilizacin del
sistema.

Introduccin al lenguaje PROLOG

37

9.- Funciones para la Depuracin de Programas

debug: Arranca el depurador (detendr la ejecucin de los programas en los puntos


espas).

debugging: Imprime el estado del depurador y los puntos espas sobre la salida actual.

nodebug: Detiene el depurador (quita el modo traza y no se detiene en ningn punto


espa).

nospy(+Pred): Borra el punto espa situado en el predicado especificado.

nospyall: Borra todos los puntos espa del programa.

notrace: Detiene el proceso de traza del programa.

spy(+Pred): Sita un punto espa 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 depuracin:
+ : spy
/c|e|r|f|u|a} goal : find
a : abort
b : break
d : display goal
f : fail
h (?) : help
l : leap
n : nodebug
r : retry
u : up
C : toggle show context

- : no spy
. : repeat find
A : alternatives
c (return,space) : creep
e : exit from Prolog
[depth]] g : goals
i : ignore
L : listing
p : print
s : skip
w : write goal

También podría gustarte