Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Manual de Prolog
Manual de Prolog
Í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
Introducción al lenguaje PROLOG 2
BIBLIOGRAFÍA RECOMENDADA
· Bibliografía Básica
· Bibliografía Complementaria
Programming in Prolog
W.F.Clocksin, C.S.Mellish
Springer-Verlag,1987
· 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 de
cláusulas de Horn. Una cláusula de Horn tiene la forma general:
Donde tanto p como las pi son símbolos predicados con sus argumentos entre paréntesis. A los
argumentos de un predicado se les denomina Términos.
Las cláusulas de Horn son expresiones condicionales, siendo el símbolo “:-” el condicional o
símbolo de la implicación (normalmente en lógica se utiliza el símbolo “¬”). Así la cláusula
anterior podría leerse de la siguiente forma:
Cuando m=0, la cláusula no tiene parte derecha, en este caso diremos que se trata de un hecho
o afirmación.
p(t1,t2,…,tn).
Cuando la cláusula no tiene parte izquierda (o cabeza), se tiene una cláusula negativa o
pregunta, este tipo de cláusulas se utilizan para realizar la entrada/salida del programa:
?p1(….),p2(….),…,pm(….)
· 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 de
Edimburgo), los símbolos de átomos (constantes), functores y predicados comienzan con una
letra minúscula, los símbolos de variables comienzan con una letra mayúscula o con un
subrayado.
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).
?p(a,X).
Para resolver el objetivo ?p(a,X) aplicando resolución lineal, se intenta su unificación con la
parte izquierda de alguna cláusula que contenga el mismo predicado/aridad. Si la unificación es
posible, se sustituye el objetivo original por la lista de objetivos de la parte derecha de la
cláusula utilizada en la unificación (con las sustituciones de variables que la unificación
implica). El proceso continúa 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 más reciente con otras alternativas para su
resolución, y se resuelve con la siguiente alternativa. Si no existen alternativas disponibles, el
objetivo de partida falla. Si se vacía la lista de objetivos, el objetivo queda resuelto.
Luego el objetivo original se ha resuelto (es cierto) con X=f(f(a,b),b), que es el resultado (o
salida) del cálculo realizado por el programa Prolog.
La estrategia de resolución descrita para aplicar el principio de resolución y que suele utilizarse
en el Prolog estándar, se denomina primero_en_profundidad (depth first), pues el árbol de
búsqueda de la solución se recorre en profundidad (se intenta resolver en primer lugar el
objetivo más reciente de la lista de objetivos). El orden de utilización de las cláusulas para
resolver un objetivo en Prolog standard es el determinado por su aparición en el programa.
2.- CLÁUSULAS
Un programa en Prolog está constituido por una secuencia de cláusulas. Estas cláusulas deben
representar 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).
3.- TÉRMINOS
4.- HECHOS
Ejemplos:
padre(luis).
padre_de(luis, pedro).
azul(cielo).
Una relación viene definida por todas las instancias que aparecen con un predicado.
Los hechos pueden introducirse en la base de hechos del intérprete de Prolog mediante una
aserción:
?- assert(padre_de(luis, pepe)).
yes.
5.- CONSULTAS
Ejemplo: Mi amigo, Vicente, busca amigos/as de mis amigos que sean millonarios/as y estén
solteros/as:
· Una consulta estará constituida por una o varias metas que Prolog deberá resolver. El
intérprete de Prolog nos devuelve más soluciones si utilizamos el punto y coma “;” cuando
no 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 como
resultado 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 la
variable con dicho valor.
Ejemplos:
7 .- REGLAS
Permiten establecer relaciones más elaboradas entre objetos, por ejemplo, relaciones
generalizadas o particularizadas, o relaciones causa-efecto. A continación, se muestran un
conjunto de ejemplos en Prolog que permiten generalizar conceptos como el de padre, familiar,
etc..
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).
7.1.-Reglas. RECURSIVIDAD
Para definir reglas más generales y flexibles, es necesario un mecanismo adicional. Para ello se
utilizará el concepto de recursividad.
Este mecanismo no es eficiente, dado que no nos permite generalizar fácilmente el concepto de
antecesor. Prolog permite utilizar definiciones recursivas, que resuelven el problema de forma
elegante.
Uno de los peligros que conlleva la recursividad, es la de realizar definiciones circulares o que
el intérprete de Prolog no sea capaz de resolver.
amigos(pedro, antonio).
amigos(pedro, flora).
...
amigos(fernando, pedro).
Esta definición aparentemente lógica provoca un error. La forma correcta de definirlo sería a
través de un nuevo predicado:
En lógica matemática no se impone un orden especial de las cláusulas y de los términos que
componen los programas. Sin embargo, en Prolog es necesario cuidar el orden de las cláusulas
dentro de un programa, debido a que el intérprete unifica la reglas en el orden secuencial en el
que 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 definiciones
distintas de antecesor_de, permutando el orden de los términos y de las cláusulas.
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.
El siguiente conjunto de directivas pueden utilizarse para lograr que la ejecución de nuestro
programa Prolog sea lo más eficiente posible.
- 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).
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ás
eficiente 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).
Introducción al lenguaje PROLOG 11
8.- DESIGUALDAD
· Desigualdad \==
Comprueba si dos términos son distintos. Por ejemplo, si dos variables tienen distintos valores
instanciados.
Ejemplos:
no_nulo(X) :- X =\= 0.
+ - * ^ potencia.
/ división real. max valor máximo de dos.
// división entera. min valor mínimo de dos.
mod resto de división entera. round redondea al entero más próximo.
abs valor absoluto. integer trunca a la parte entera.
** potencia. float convierte en un valor real.
Introducción al lenguaje PROLOG 12
igual1(X, Y) :- X =:= Y.
igual2(X, Y) :- X == Y.
igual3(X, Y) :- X = Y.
igual4(X,X).
incremento(X,Y) :- Y is X+1.
igual5(X, Y) :- X is Y.
Los operadores antes mencionados, aunque parten de conceptos muy distintos, poseen
comportamientos similares, lo cuál puede inducir a errores. A continuación se muestra una
tabla comparativa de todas las posibilidades existentes.
Operador =:= == = = is
Ejemplo igual1 igual2 igual3 igual4 igual5
Igual?(3,3). yes yes yes yes yes
Igual?(1,3). no no no no no
Igual?(1+2,3). yes no no no no
Igual?(3,1+2). yes no no no yes
Igual?(X,1+2). * no X=1+2 X=1+2 X=3
Igual?(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=3
Igual?(‘hola’,’hola’). ** yes yes yes yes
Igual?(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.
Introducción al lenguaje PROLOG 13
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 funciona
igual1(constante, vlibre) no funciona
igual1(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 funciona
igual5(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(+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 ser
una 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 un
predicado.
Introducción al lenguaje PROLOG 14
Función escalón
-6 -3 0 3 6 9 ì0, x<3
ï
f ( x) = í2, 3£ x<6
ï4, 6£ x
î
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 cláusulas cuando sólo haría falta comprobar una.
¡fallo!
Introducción al lenguaje PROLOG 15
Existe un predicado que capaz de ‘cortocircuitar’ la búsqueda una vez que es evaluado: el
corte, representado con el símbolo de admiración “!”.El corte, es un predicado que siempre se
evalúa como cierto y que impide que se continúen evaluando el resto de reglas.
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 una
interpretación procedimental para entender este predicado.
¡fallo!
f(X,0) :- X < 3, !.
f(X,2) :- 3 =< X, X < 6, !.
f(X,4) :- 6 =< X.
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é se
ha hecho mal?. El problema es que el nuevo programa se basa en un programa semánticamente
incorrecto, si eliminásemos el corte, observaríamos que al eliminar el operador de corte
obtenemos un programa incorrecto:
¡Este tipo de corte (Corte Rojo) debe emplearse con sumo cuidado!
El motivo de perder el modo f(+,+) es debido a una interacción poco obvia entre la
equiparación, las condiciones y el corte. El programa realmente debería ser:
?- f(2, X).
X=0;
X=2;
X=4
Función rampa
6
1 ì3 - x , x<3
0 ï
-3 -2 -1
-1
0 1 2 3 4 5 6 7 8 9 10 g ( x ) = í x - 3, 3£ x < 6
ï -
a
-2
î9 x , 6£ x
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.
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.
Introducción al lenguaje PROLOG 17
Si se trazan algunos ejemplos sencillos se pueden observar los posibles casos que pueden
presentarse 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 otra
clá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. Por
ejemplo, en g(2,1) o g(2, Z). Þ El intérprete retrocede con cierto; debido al corte no se intenta
verificar otra cláusula. El intérprete responde: Sí.
13.- FALLO
fail (fallo) es un predicado que siempre produce fallo. Es útil cuando queremos detectar casos
explí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 caso
vamos a suponer que entrada=1 equivale a cierto).
nand7(0, _, _, _, _, _, _).
nand7(_, 0, _, _, _, _, _).
nand7(_, _, 0, _, _, _, _).
nand7(_, _, _, 0, _, _, _).
nand7(_, _, _, _, 0, _, _).
nand7(_, _, _, _, _, 0, _).
nand7(_, _, _, _, _,_, _0).
nand7(1, 1, 1, 1, 1, 1, 1) :- !, fail.
nand7(_, _, _, _, _, _, _).
14.- NEGACIÓN
Existe un predicado de negación en Prolog (not) que está implementado como negación por
fallo, esto quiere decir que se evalúa como falso cualquier cosa que Prolog sea incapaz de
verificar que su predicado argumento es cierto.
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).
Introducción al lenguaje PROLOG 18
?- millonario(X).
X = flora ;
X = antonio
?- pobre(X).
No.
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: dados tres hechos que describen los lados de un triángulo, escribir un programa que
devuelva las longitudes ordenadas de forma ascendente: ordena(-,-,-).
lado(a, 5).
lado(b, 3).
lado(c, 4).
Para obtener un programa no determinista, lo que se puede plantear es; generar de forma
combinatoria soluciones posibles y comprobar si son correctas. El método de búsqueda de
Prolog se encarga de retroceder cuando una solución no es válida.
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.
primoroso(zorro).
primoroso(oso).
amoroso(oso).
astuto(zorro).
Consulta:
?-primoroso(X), amoroso(X).
Mecanismo de resolución:
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 términos (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:
· Debido al frecuente uso de este tipo de estructura, Prolog permite una notación abreviada
para representar listas. Los elementos de la lista aparecen separados por comas, y la lista
completa aparece entre corchetes.
longitud(Xs, N)
longitud([ ], 0).
longitud([X | Xs], N) :- longitud(Xs, N1), N is N1+1.
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º.- 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 (se
elimina la primera aparición 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).
Introducción al lenguaje PROLOG 22
5º.- Eliminación de todas las apariciones de un elemento X en una lista L1, como consecuencia
se obtiene la lista L2.
borrar(X,L1,L2)
invertir(L1,L2)
invertir([],[]).
invertir([X|C],Z) :- invertir(C,C1),concatenar(C1,[X],Z).
Ejemplos:
?-[X,libro]=[lapiz,Y].
X=lapiz
Y=libro
Yes
?-[X,libro]=[Y,lapiz].
No
Introducción al lenguaje PROLOG 23
· Ejercicio 1
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 este
problema podemos utilizar el fallo y el corte:
· Solución 2ª
· Solución 3ª
· Solución 4ª
· Ejercicio 2
Función Sierra
8
7
6
5
4
3
2
1
0
ìnodefinida x < 0
ï x,
-1
-3
-2
0 3 6 9 12 ïï 0£ x<3
h( x) = í x - 3, 3 £ x < 6
ï x - 6, 6 £ x < 9
ï
ïînodefinida x ³ 9
Soluciones…Ejercicio 2
· Solución 1ª
· 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ª
· Solución 4ª
· Ejercicio 3
Soluciones…Ejercicio 3
· Solución determinista
· Solución no determinista
permuta2(X,Y, X,Y).
permuta2(X,Y, Y,X).
· Ejercicio 4
Soluciones…Ejercicio 4
v(X,Y) :- vertice(X,Y).
· Ejercicio 5
Enunciado: Escribir un programa procedimental que, dados tres valores: [a, b y c], responda si
es 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.
trianguloq(A,B,C) ...
Soluciones…Ejercicio 5
· Solución en PASCAL
BEGIN
Ordena3 (X, Y, Z);
IF (X > 0) AND (X + Y > Z) THEN (* Es_triangulo *)
BEGIN
IF (X = Z) THEN
Introducción al lenguaje PROLOG 27
WRITELN (‘Equilatero’);
ELSE IF (X = Y) OR (Y = Z)
WRITELN (‘Isósceles’);
ELSE
WRITELN (‘Escaleno’);
RETURN (TRUE);
END
ELSE RETURN (FALSE);
END;
· Planteamiento 1º
En primer lugar, se plantean las condiciones necesarias para poder construir un triángulo
T(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,b
a+c>b si b>a,c
b+c>a si a>b,c
T(a,b,c) es equilátero si
a=b=c
T(a,b,c) es isósceles 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
· Solución 1ª
· Solución 2ª
· Planteamiento 2º
La solución anterior es efectiva, pero no capta la toda la información que disponemos sobre el
problema porque no se ha estructurado del todo bien. La solución propuesta enumeran todos los
casos 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 que
x<y<z, podemos simplificar dicha restricción. De paso podremos simplificar las demás
tambié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 si
x=z (puesto que x<y<z, si x=z => x=y=z)
T(x,y,z) es isósceles 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
· Solución 3ª
· Ejercicio 6
Enunciado:
A).- Dado el siguiente árbol genealógico (ver figura 1), crear un base de hechos que lo
represente y el conjunto de cláusulas necesarias que me permitan establecer las relaciones
habituales 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 ?
B).- Se modificará el programa anterior, para permitir la inserción de nuevos hechos en nuestra
base. 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 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 Genealógico:
Familia 1 Familia 2
Antonio---Cándida José---MªAngeles
Juan------Sara
Sonia
C).- En este apartado se pretende modelizar la Computación del Parentesco entre dos
personas de una familia, en primer lugar definiremos un conjunto de conceptos necesarios para
poder realizar el cálculo:
• Línea es el conjunto o serie de grados que pueden existir entre dos personas; puede
ser 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 pero
tienen ascendientes comunes: hermanos, tíos, primos, sobrinos, etc.
Introducción al lenguaje PROLOG 30
• GRADO es, en materia de parentesco, cada una de las generaciones existentes entre
dos personas relacionadas por vínculos de sangre. Así del padre al hijo hay una
generación o grado, entre abuelo y nieto existen dos grados.
· Derecho Civil: existen tantos grados como generaciones, así en la línea recta entre el nieto
y el abuelo existen dos grados de parentesco. Si utilizamos la línea colateral, para calcular
el grado de parentesco entre dos individuos, se asciende hasta el primer antepasado común
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 Canónico: en el caso de la línea recta el cómputo es idéntico que en el caso del
derecho civil. En la línea colateral se cuentan las generaciones o grados de la línea más
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 encontrarían en segundo grado.
Esta computación rige solamente para el matrimonio canónico 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.
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).
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.
Introducción al lenguaje PROLOG 31
Apéndice.- SWI_Prolog
http://grial.uc3m.es/~docweb/pl2/index.html
Una vez arrancado el intérprete Prolog , utilizaremos el predicado consult/1 Para cargar el
conjunto de hechos y reglas que contiene el fichero. No debe utilizarse la extensión .pl
Una forma abreviada de cargar el programa puede realizarse utilizando los corchetes
[program1].
Introducción al lenguaje PROLOG 32
Para realizar preguntas simples al intérprete, podemos utilizar predicados simples que hayamos
predefinido en el programa, dejando alguno de sus términos sin instanciar.
Ejemplo:
?-p(a,X).
?-saldo_cuenta(maria,Z).
El intérprete SWI_Prolog nos proporciona una pequeña 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 sección especificada, las secciones se identifican
por números separados por un guión: 2-3 (sección 2.3 del
manual).
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 (en
minú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 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
Introducción al lenguaje PROLOG 33
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.
· display(+Term): Escribe el término Term sobre la salida estándar del dispositivo. Este
predicado suele emplearse normalmente para examinar la representación interna de un
término.
· get(-Char): Lee de la entrada actual caracteres y unifica Char con el próximo carácter
introducido (distinto al carácter 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 próximo carácter
introducido. 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 .
· skip(+Char): Lee y salta caracteres desde la entrada estándar hasta que encuentra el
carácter Char.
· writeq(+Term): Escribe el término Term sobre la salida estándar (sitúa el término entre
comillas). En este predicado, los términos pueden ser vueltos a leer con el predicado
read/1.
Introducción al lenguaje PROLOG 34
· seen: Cierra el fichero actualmente abierto, y devuelve la entrada estándar del dispositivo
al teclado del terminal.
· 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 estándar
del dispositivo a la pantalla del terminal.
· [+Filespec]: Lee las cláusulas contenidas en el fichero especificado y las inserta en la base
de datos (es una acción similar a ejecutar el predicado consult).
· consult(+File): Lee un fichero con formato Prolog (el fichero va sin extensión aunque por
defecto buscará el fichero File o File.pl, toma las cláusulas que encuentre en ese fichero y
las inserta en la base de datos
· shell: Inicia un shell interactivo con Unix. El shell finaliza al teclear exit.
· statistics: Muestra una tabla con información estadística acerca de la utilización del
sistema.
Introducción al lenguaje PROLOG 36
· debugging: Imprime el estado del depurador y los puntos espías sobre la salida actual.
· spy(+Pred): Sitúa un punto espía en el todos los predicados especificados por Pred.
Opciones de depuración:
+ : spy - : no spy
/c|e|r|f|u|a} goal : find . : repeat find
a : abort A : alternatives
b : break c (return,space) : creep
d : display goal e : exit from Prolog
f : fail [depth] g : goals
h (?) : help i : ignore
l : leap L : listing
n : nodebug p : print
r : retry s : skip
u : up w : write goal
C : toggle show context