2009-09-15 24 views
9

La siguiente historia es de N. Wirth (1976) Algorithms + Datastructures = Programs.¿Cómo puedo implementar "Soy mi propio abuelo" en Prolog?

que casó con una viuda (llamémosla W) que tenía una hija mayor de edad (llamarla D). Mi padre (F), que nos visitó con bastante frecuencia, se enamoró de mi hijastra y se casó con ella. Por lo tanto, mi padre se convirtió en mi yerno y mi hijastra se convirtió en mi madre. Unos meses después, mi esposa dio a luz a un hijo (S1), que se convirtió en el cuñado de mi padre, así como como mi tío. Esta esposa de mi padre, es decir, mi hijastra, también tenía un hijo (S2).

que estoy tratando de modelar estas relaciones en el prólogo por lo que finalmente voy a ser capaz de escribir:

| ?- grandfather(i,i). 

Y que me dieron un "sí" o un "No" en la si soy o no mi propio abuelo

Este es el código que he escrito hasta ahora (grandpa.pl):

aunt(X,Y):- 
    sibling(X,Z), 
    parent(Z,Y), 
    female(X). 

brother(X,Y):- 
    sibling(X,Y), 
    male(X). 

brother_in_law(X,Y):- 
    child(X,Z), 
    married(Z,W), 
    parent(W,Y), 
    not(sibling(X,Y)), 
    male(X). 

brother_in_law(s1,f). 

child(X,Y):- 
    parent(Y,X). 

daughter(X,Y):- 
    parent(Y,X), 
    child(X,Y), 
    female(X). 

daughter(d,w). 

father(X,Y):- 
    parent(X,Y), 
    male(X). 

father(f,i). 

father_in_law(X,Y):- 
    child(X,Z), 
    married(Y,Z), 
    not(child(X,Y)), 
    male(X). 

grandparent(X,Y):- 
    parent(X,Z), 
    parent(Z,Y). 

grandmother(X,Y):- 
    grandparent(X,Y), 
    female(X). 

grandfather(X,Y):- 
    grandparent(X,Y), 
    male(X). 

grandchild(X,Y):- 
    child(X,Z), 
    child(Z,Y). 

married(X,Y):- 
    wife(X,Y), 
    female(X). 

married(X,Y):- 
    husband(X,Y), 
    male(X). 

married(i,w). 
married(f,d). 

mother(X,Y):- 
    parent(X,Y), 
    female(X). 

parent(X,Y):- 
    child(Y,X). 

sibling(X,Y):- 
    parent(Z,X), 
    parent(Z,Y). 

sister(X,Y):- 
    sibling(X,Y), 
    female(X). 

son(X,Y):- 
    parent(Y,X), 
    male(X). 

son(s1,w). 
son(s2,d). 

son_in_law(X,Y):- 
    child(X,Z), 
    not(child(X,Y)), 
    married(Z,Y), 
    male(X). 

son_in_law(f,i). 

step_daughter(X,Y):- 
    child(X,Z), 
    married(Z,Y), 
    not(child(X,Y)), 
    female(X). 

step_daughter(d,i). 

step_parent(X,Y):- 
    married(X,Z), 
    parent(Z,Y), 
    not(parent(X,Y)). 

step_father(X,Y):- 
    step_parent(X,Y), 
    male(X). 

step_mother(X,Y):- 
    step_parent(X,Y), 
    female(X). 

step_mother(d,i). 

uncle(X,Y):- 
    sibling(X,Z), 
    parent(Z,Y), 
    male(X). 

uncle(s1,i). 

En este momento estoy teniendo muchos problemas con las definiciones circulares para que me meto en bucles infinitos cuando se ejecuta la consulta : abuelo (yo, yo).

Por ejemplo, tengo:

(1 ms) sí {trace} | ? - abuelo (yo, yo). 1 1 Llamada: abuelo (i, i)?
2 2 Llamar: abuelo (i, i)?
3 3 Llamar: padre (i, _103)?
4 4 Llamar: hijo (_127, i)?
5 5 Llamar: padre (i, _151)?
6 6 Llamar: hijo (_175, i)?
7 7 Llamar: padre (i, _199)?
8 8 Llamar: hijo (_223, i)?
9 9 Llamar: padre (i, _247)?
10 10 Llamar: hijo (_271, i)?
11 11 Llamar: padre (i, _295)?
12 12 Llamar: hijo (_319, i)?
13 13 Llamar: padre (i, _343)?
14 14 Llamar: hijo (_367, i)?
15 15 Llamar: padre (i, _391)?
...

Esto se debe a que los niños se define como ha tener un padre, y el padre se autodefine ha de tener un hijo (como se verá en los predicados anteriores he publicado).

¿Alguien me puede ayudar a volver a definir mis predicados para estas relaciones para poder determinar si soy mi propio abuelo?

+0

Je, yo en realidad tenía que hacer eso para mi clase de AI. Me pregunto si aún tengo el código ... Lo veré cuando llegue a casa. Recuerdo que también lastimó mi cerebro. –

+5

Usan Prolog en West Virgina? ;-) –

+0

@ T.E.D .: Shh! ¡TheTXI te escuchará! –

Respuesta

3

Mi curso prólogo ha sido hace mucho mucho tiempo, pero ¿qué pasa con la eliminación de

parent(X,Y):- 
    child(Y,X). 

y sólo la sustitución de cualquier uso de parent(A,B) con child(B,A)? Todavía puede agregar datos sobre los padres porque la regla inversa todavía está disponible; también puede eliminarla, pero en ese caso ya no puede usar ningún dato sobre los padres y tendrá que escribir todos sus datos como hijo (a, b) también.

Es lo mismo ¿no?

1

Tenga en cuenta que mi conocimiento de Prolog es antiguo (y nunca que en el fondo) ...

creo que es necesario hacer los padres (o niño) primario (no dependiente de otras relaciones).

child(X,Y):- 
    parent(Y,X). 

parent(X,Y):- 
    child(Y,X). 

es lo que probablemente está causando los bucles.

5

que eliminan todo lo que era necesario en el código y cambiaron algunas cosas y esto es lo que terminó con:

% married(Husband, Wife) 
married(i,w). 
married(f,d). 

Uno podría suponer que married(X,Y) :- married(Y,X), pero conduce a pruebas circulares desagradables, por lo que simplemente pondrá al marido primero por convención.

Acerca de la paternidad, surge un problema similar. Necesitamos considerar a los padrastros como padres verdaderos, porque el enigma depende de ello. ¡Sabemos que nunca podrás ser tu propio ancestro biológico!

Sin embargo, parent(X,Y) :- parent(Z,Y), married(X,Z) tiene los mismos problemas, entonces acabo de hacer que bio_parent denote paternidad biológica.

bio_parent(f,i). 
bio_parent(w,d). 
bio_parent(w,s1). 
bio_parent(i,s1). 
bio_parent(d,s2). 
bio_parent(f,s2). 

Tenga en cuenta que tenemos que ser explícito acerca de ambos padres, ya que no hay manera de concluir la paternidad biológica del matrimonio! Además, su forma de especificación fue problemática. Tenías algo como:

son(X,Y) :- child(X,Y), male(X). 
son(a,b). 

Sin embargo, a partir de estas reglas Prolog no podría inferir child(a,b), por lo que terminó poco con hijos que no eran niños! Esto ocurrió varias veces en tu código. Si obtiene b de a, siempre indique a como hecho. A primera vista, esto podría parecer una deficiencia de Prolog, pero no lo es. Recuerde que cada cláusula es solo una forma de probar un determinado predicado. En el ejemplo anterior, indicó que cada hijo varón es un hijo, y también a que resulta ser hijo de b. En ninguna parte se dice que ser un niño varón es la única forma en que alguien podría ser un hijo, sin embargo, a podría ser la excepción.

El siguiente es un poco prolijo ya que nuestra definición de married nos obliga a tratar a los padrastros por separado de los padrastros. Sin embargo, los unificamos a los padres del paso .

step_father(X,Y) :- married(X,Z),bio_parent(Z,Y),\+bio_parent(X,Y). 
step_mother(X,Y) :- married(Z,X),bio_parent(Z,Y),\+bio_parent(X,Y). 
step_parent(X,Y) :- step_father(X,Y). 
step_parent(X,Y) :- step_mother(X,Y). 

Como dije anteriormente, ¡debemos considerar a los padrastros como padres!

parent(X,Y) :- step_parent(X,Y). 
parent(X,Y) :- bio_parent(X,Y). 

grandparent(X,Y):- 
    parent(X,Z), 
    parent(Z,Y). 

También hubo algunos otros errores en su código que saqué, solo le muestro algunos ejemplos para que pueda aprender de ello.

primer lugar, aquí se dice que las esposas femeninos están casados, y los esposos varones están casados. Entonces, las esposas masculinas no estarían casadas. Sin embargo, debería ser al revés, ¡las mujeres casadas se llaman esposas!

% wrong: 
% 
% married(X,Y):- 
% wife(X,Y), 
% female(X). 
% 
% married(X,Y):- 
% husband(X,Y), 
% male(X). 
% 
% right: 
% wife(X,Y) :- married(Y,X). % according to our new definition of 'married' 
% husband(X,Y) :- married(X,Y). 

Aquí he añadido la última línea, ya que normalmente no se considera su propio hermano:

% sibling(X,Y):- 
% parent(Z,X), 
% parent(Z,Y), 
% X \= Y. % added this 

Los dos últimos son hechos en el predicado mal otra vez. Básicamente, anula la deducción de Prolog . ¡Deben deducirse, no como hechos!

% son_in_law(f,i). 
% step_mother(d,i). 

Ahora, probar el programa como este. Y no se sorprenda: ¡usted no será el único en ser su propio abuelo! ;-)

0
couples(i,w). 
mother_of(w,d). 
father_of(f,i). 
couples(f,d). 
son_in_law(f,i). 
mother_of(d,i). 
mother_of(w,s1). 
mother_of(d,s2). 
grand(F,C):- son_in_law(F,C),couples(H,D),mother_of(D,C). 
grand(F,C):- father_of(F,D),father_of(D,C). 

consulta

?-grand(i,i). 
Cuestiones relacionadas