Programación Declarativa

Introducción:

Las prácticas de Programación Lógica se realizarán utilizando el intérprete SWI-Prolog. Dependiendo de la implementación, el intérprete puede ejecutarse con la orden prolog o pl:

  
$ pl
Welcome to SWI-Prolog (Version 5.0.0)
Copyright (c) 1990-2002 University of Amsterdam.
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.

For help, use ?- help(Topic). or ?- apropos(Word).

?-
  
Para salir de Prolog:
  
?- halt.
$
  
Prolog espera que todas las líneas acaben en un punto. Por ejemplo:
  
$ pl
Welcome to SWI-Prolog (Version 5.0.0)
Copyright (c) 1990-2002 University of Amsterdam.
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.

For help, use ?- help(Topic). or ?- apropos(Word).

?- halt
|    .
$
  
Para introducir un programa lógico se hace de la siguiente manera:
  
?- [user].
|:
  
Esto informa al intérprete de que se van a introducir las cláusulas del programa:
  
|: numero_natural(0).
|: numero_natural(siguiente(Numero)) :- numero_natural(Numero).
  
Para acabar de introducir el programa lógico, teclear ^D.
  
|: % user compiled 0.01 sec, 512 bytes

Yes
?- numero_natural(siguiente(0)).

Yes
?- numero_natural(X).

X = 0 ;

X = siguiente(0) ;

X = siguiente(siguiente(0)) 

Yes
?- 
  
El punto y coma fuerza el retroceso por el árbol de resolución.

Para leer el programa lógico de fichero, se utiliza la orden consult o directamente el nombre del fichero entre corchetes. Por ejemplo:

  
?- consult(persona).
% persona compiled 0.01 sec, 10,332 bytes
Yes
?- [persona].
% persona compiled 0.01 sec, 0 bytes

Yes
?- 
  
Ambas leen el fichero persona.pl del subdirectorio activo. En caso de que la extensión o el directorio del fichero sean distintos, habrá que darle el nombre del fichero completo entre apóstrofes:
  
?- consult('persona.pdb').
% persona.pdb compiled 0.01 sec, 10,176 bytes

Yes
?- ['persona.pdb'].
% persona.pdb compiled 0.01 sec, 0 bytes

Yes
?- 
  

Ejercicio:

Supón una familia con un árbol genealógico como se explica a continuación:

Supón que se define tres predicados: Construye un programa lógico compuesto por hechos que defina a esta familia.

Prueba las respuestas a preguntas del tipo:

  
:- progenitor('Maria',X).
:- progenitor(X,'Roberto').
  
Completa ahora el programa introduciendo reglas para definir las relaciones padre(X,Y) y madre(X,Y), que significarán que X es el padre de Y y que X es la madre de Y, respectivamente.

Prueba y explica las respuestas a preguntas tales como:

  
:- padre(X,'Ramon').
:- padre(X,'Maria').
:- madre('Juan',X).
  
Haz lo mismo con las relaciones hijo e hija. Implementa las relaciones hermano y hermana mediante las reglas:
  
hermano(X,Y) :- progenitor(Z,X), progenitor(Z,Y), hombre(X).
hermana(X,Y) :- progenitor(Z,X), progenitor(Z,Y), mujer(X).
  
Prueba y explica la respuesta a preguntas como
  
:- hermano('Pedro',X).
  
Se puede ver que en este caso aparecen dos problemas: Plantea una posible solución para el primer problema. El segundo problema se resuelve introduciendo las cláusulas
  
distinta_persona(X,X) :- !,fail.
distinta_persona(X,Y).
  
y añadiendo el literal distinta_persona(X,Y) a las claúsulas que definen las relaciones hermano y hermana. Prueba ahora la respuesta a la pregunta:
  
hermano(X,Y).
  
Puedes intentar definir y probar toda clase de relaciones familiares: sobrino/a, tío/a, esposo/a, abuelo/a, cuñado/a, primo/a...

Estudia el problema que puede aparecer al cambiar el orden de aparición de los literales en la cola de las claúsulas introducidas.