Programación Declarativa – Prácticas de Prolog resueltas (I)

Programación Declarativa – Prácticas de Prolog resueltas (I)
13/03/11


Este post va dedicado especialmente a los estudiantes de Ingeniería Informática, aunque también le resultará de gran utilidad a cualquier persona que esté empezando a estudiar algo de Inteligencia Artificial utilizando el lenguaje Prolog. A continuación voy a presentar una serie de ejercicios propuestos, así como una posible solución a los mismos. Cabe destacar que es posible que haya algún pequeño error en las soluciones, pero aún así os servirán para comprender el funcionamiento de Prolog.

Pues bien, sin más preámbulos, aquí tenéis los ejercicios:

Enunciado

El siguiente programa Prolog especifica una base de datos deductiva sobre relaciones familiares. Completar el código dado, respondiendo a los diferentes apartados, mediante la lectura de estos fragmentos del Génesis.

“He aquí la descendencia de Teraj: Teraj engendró a Abram (posteriormente llamado `Abraham’, que significa `Padre de multitud’), Najor, y Harán. Harán engendró a Lot … La mujer de Abram se llamaba Sarai (o Sara) y la de Najor Melca, hija de Harán, padre de Melca y de Jesca.”

“Sarai, la mujer de Abram, no le había dado hijos, pero ella tenía una esclava egipcia de nombre Agar. … tomó a Agar y se la dio por mujer a Abram, … Agar parió un hijo a Abram y a este hijo tenido de Agar, Abram le llamó Ismael.”

Estando en la tierra de Guerar, Abram confeso que: ” es verdad que ella (Sarai) también es mi hermana, hija de mi padre pero no de mi madre, y ahora es mi mujer.”

“Sara, pues, concibió y parió un hijo en su vejez, en el tiempo predicho por Dios. Y Abraham llamó al hijo que le nació Isaac (que significa `el que ríe’).” Isaac casó con Rebeca, “hija de Batuel, el que Melca parió a Najor” y hermana de Labán. Isaac y Rebeca tuvieron dos hijos, Esaú y Jacob, pero ésta es otra historia.

El código dado por el ejercicio es:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
%%% HECHOS
 
padre(abraham,isaac).
padre(haran,lot).
padre(haran,melca).
padre(haran,jesca).
hombre(isaac).
hombre(lot).
mujer(melca).
mujer(jesca).
 
%%% REGLAS
 
ascendiente_directo(X, Y) :- (padre(X, Y) madre(X, Y)).
ascendiente(X, Z) :- ascendiente_directo(X, Z).
ascendiente(X, Z) :- ascendiente_directo(X, Y), ascendiente(Y, Z).
hijo(X,Y) :- hombre(X), ascendiente_directo(Y,X).
hija(X,Y) :- mujer(X), ascendiente_directo(Y,X).

Se pide responder a los siguientes apartados:

  • Completar la base de datos con los hechos extraídos del fragmento del génesis anterior.
  • Definir las relaciones: ascendente, descendente, abuelo, hermano, tío, sobrino y primo.
  • Definir un predicado que nos informe de las relaciones que hoy consideramos incestuosas.
Solución

La solución que propongo es la siguiente (ya todo el código junto):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
				%HECHOS
%hombre
hombre(abraham).
hombre(isaac).
hombre(lot).
hombre(najor).
hombre(ismael).
hombre(haran).
hombre(teraj).
hombre(batuel).
hombre(laban).
hombre(esau).
hombre(jacob).
 
%mujer
mujer(rebeca).
mujer(melca).
mujer(jesca).
mujer(sara).
mujer(agar).
 
%esclava
esclava(agar).
 
%padre
padre(abraham, isaac).
padre(abraham, ismael).
padre(haran, lot).
padre(haran, melca).
padre(haran, jesca).
padre(teraj, abraham).
padre(teraj, sara).
padre(teraj, najor).
padre(teraj, haran).
padre(batuel, rebeca).
padre(batuel, laban).
padre(najor, batuel).
padre(isaac, esau).
padre(isaac, jacob).
 
%madre
madre(agar, ismael).
madre(sara, isaac).
madre(rebeca, esau).
madre(rebeca, jacob).
madre(melca, batuel).
 
%casados 
casado(abraham, sara).
casado(isaac, rebeca).
casado(najor, melca).
 
 
				%REGLAS
%hijo
hijo(X, Y) :- padre(Y, X), hombre(X).
hija(X, Y) :- padre(Y, X), mujer(X).
 
%casados
casados(X, Y) :- casado(X, Y) casado(Y, X).
 
%ascendiente_directo
ascendiente_directo(X, Y) :- padre(X, Y) madre(X, Y).
 
%abuelo
abuelo(X, Y) :- padre(X, Z), ascendiente_directo(Z, Y).
 
%abuela
abuela(X, Y) :- madre(X, Z), ascendiente_directo(Z, Y).
 
%nieto
nieto(X, Y) :- (abuelo(Y, X) abuela(Y, X)), hombre(X).
 
%nieta
nieta(X, Y) :- (abuelo(Y, X) abuela(Y, X)), mujer(X).
 
%ascendiente
ascendiente(X, Y) :- ascendiente_directo(X, Y).
ascendiente(X, Y) :- abuelo(X, Y) abuela(X, Y).
 
%hermano
hermano(X, Y) :- hombre(X), (ascendiente_directo(Z, X), ascendiente_directo(Z, Y)), X\=Y.
 
%hermana
hermana(X, Y) :- mujer(X), (ascendiente_directo(Z, X), ascendiente_directo(Z, Y)), X\=Y.
 
%hermanos
hermanos(X, Y) :- hermano(X, Y) hermana(X, Y) hermano(Y, X) hermana(Y, X).
 
%descendiente_directo
descendiente_directo(X, Y) :- ascendiente_directo(Y, X).
 
%descendiente
descendiente(X, Y) :- descendiente_directo(Y, X).
descendiente(X, Y) :- nieto(X, Y) nieta(X, Y).
 
%tio_carnal
tio_carnal(X, Y) :- hermanos(X, Z), ascendiente_directo(Z, Y), hombre(X).
tia_carnal(X, Y) :- hermanos(X, Z), ascendiente_directo(Z, Y), mujer(X).
 
%tio_no_carnal
tio_no_carnal(X, Y) :- casados(X, Z), tia_carnal(Z, Y).
tia_no_carnal(X, Y) :- casados(X, Z), tio_carnal(Z, Y).
 
%tio
tio(X, Y) :- tio_carnal(X, Y) tio_no_carnal(X, Y), not(padre(X,Y)), X\==Y.
 
%tia
tia(X, Y) :- tia_carnal(X, Y) tia_no_carnal(X, Y), not(madre(X,Y)), X\==Y.
 
%sobrino
sobrino(X, Y) :- hombre(X), (tio(Y, X) tia(Y, X)).
 
%sobrina
sobrina(X, Y) :- mujer(X), (tio(Y, X) tia(Y, X)).
 
%primo
primo(X, Y) :- hombre(X), (tio(Z, X) tia(Z, X)), ascendiente_directo(Z, Y),X\==Y.
 
%prima
prima(X, Y) :- mujer(X), (tio(Z, X) tia(Z, X)), ascendiente_directo(Z, Y),X\==Y.
 
%primos
primos(X, Y) :- primo(X, Y) primo(Y, X) prima(X, Y) prima(Y, X).
 
%incestuosos
incestuosos(X, Y) :- casados(X, Y), hombre(X), mujer(Y),(hermanos(X, Y) primos(X, Y) ascendiente_directo(X, Y) descendiente_directo(X, Y) abuelo(X, Y) nieto(X, Y) abuela(X, Y) nieta(X, Y) tio(X, Y) tia(X, Y) sobrino(X, Y) sobrina(X, Y)).

Espero que os sirva. Y si quereis aprender Programación Declarativa y Prolog, os recomiendo el libro “Programación lógica. Teoría y Práctica”, de Pascual Julián Iranzo y María Alpuente Frasnedo, que está muy bien escrito y completamente en español.

Escrito por sgm


Puedes dejar un comentario, o referenciar este post desde tu sitio web.

Responde